/*! markdown-it 3.0.3 https://github.com//markdown-it/markdown-it @license MIT */
!function (e) {
    if ("object" == typeof exports && "undefined" != typeof module)module.exports = e(); else if ("function" == typeof define && define.amd)define([], e); else {
        var f;
        "undefined" != typeof window ? f = window : "undefined" != typeof global ? f = global : "undefined" != typeof self && (f = self), f.markdownit = e()
    }
}(function () {
    var define, module, exports;
    return (function e(t, n, r) {
        function s(o, u) {
            if (!n[o]) {
                if (!t[o]) {
                    var a = typeof require == "function" && require;
                    if (!u && a)return a(o, !0);
                    if (i)return i(o, !0);
                    var f = new Error("Cannot find module '" + o + "'");
                    throw f.code = "MODULE_NOT_FOUND", f
                }
                var l = n[o] = {exports: {}};
                t[o][0].call(l.exports, function (e) {
                    var n = t[o][1][e];
                    return s(n ? n : e)
                }, l, l.exports, e, t, n, r)
            }
            return n[o].exports
        }

        var i = typeof require == "function" && require;
        for (var o = 0; o < r.length; o++)s(r[o]);
        return s
    })({
        1: [function (require, module, exports) {
// List of valid entities
//
// Generate with ./support/entities.js script
//
            'use strict';

            /*eslint quotes:0*/
            module.exports = {
                "Aacute": "\u00C1",
                "aacute": "\u00E1",
                "Abreve": "\u0102",
                "abreve": "\u0103",
                "ac": "\u223E",
                "acd": "\u223F",
                "acE": "\u223E\u0333",
                "Acirc": "\u00C2",
                "acirc": "\u00E2",
                "acute": "\u00B4",
                "Acy": "\u0410",
                "acy": "\u0430",
                "AElig": "\u00C6",
                "aelig": "\u00E6",
                "af": "\u2061",
                "Afr": "\uD835\uDD04",
                "afr": "\uD835\uDD1E",
                "Agrave": "\u00C0",
                "agrave": "\u00E0",
                "alefsym": "\u2135",
                "aleph": "\u2135",
                "Alpha": "\u0391",
                "alpha": "\u03B1",
                "Amacr": "\u0100",
                "amacr": "\u0101",
                "amalg": "\u2A3F",
                "AMP": "\u0026",
                "amp": "\u0026",
                "And": "\u2A53",
                "and": "\u2227",
                "andand": "\u2A55",
                "andd": "\u2A5C",
                "andslope": "\u2A58",
                "andv": "\u2A5A",
                "ang": "\u2220",
                "ange": "\u29A4",
                "angle": "\u2220",
                "angmsd": "\u2221",
                "angmsdaa": "\u29A8",
                "angmsdab": "\u29A9",
                "angmsdac": "\u29AA",
                "angmsdad": "\u29AB",
                "angmsdae": "\u29AC",
                "angmsdaf": "\u29AD",
                "angmsdag": "\u29AE",
                "angmsdah": "\u29AF",
                "angrt": "\u221F",
                "angrtvb": "\u22BE",
                "angrtvbd": "\u299D",
                "angsph": "\u2222",
                "angst": "\u00C5",
                "angzarr": "\u237C",
                "Aogon": "\u0104",
                "aogon": "\u0105",
                "Aopf": "\uD835\uDD38",
                "aopf": "\uD835\uDD52",
                "ap": "\u2248",
                "apacir": "\u2A6F",
                "apE": "\u2A70",
                "ape": "\u224A",
                "apid": "\u224B",
                "apos": "\u0027",
                "ApplyFunction": "\u2061",
                "approx": "\u2248",
                "approxeq": "\u224A",
                "Aring": "\u00C5",
                "aring": "\u00E5",
                "Ascr": "\uD835\uDC9C",
                "ascr": "\uD835\uDCB6",
                "Assign": "\u2254",
                "ast": "\u002A",
                "asymp": "\u2248",
                "asympeq": "\u224D",
                "Atilde": "\u00C3",
                "atilde": "\u00E3",
                "Auml": "\u00C4",
                "auml": "\u00E4",
                "awconint": "\u2233",
                "awint": "\u2A11",
                "backcong": "\u224C",
                "backepsilon": "\u03F6",
                "backprime": "\u2035",
                "backsim": "\u223D",
                "backsimeq": "\u22CD",
                "Backslash": "\u2216",
                "Barv": "\u2AE7",
                "barvee": "\u22BD",
                "Barwed": "\u2306",
                "barwed": "\u2305",
                "barwedge": "\u2305",
                "bbrk": "\u23B5",
                "bbrktbrk": "\u23B6",
                "bcong": "\u224C",
                "Bcy": "\u0411",
                "bcy": "\u0431",
                "bdquo": "\u201E",
                "becaus": "\u2235",
                "Because": "\u2235",
                "because": "\u2235",
                "bemptyv": "\u29B0",
                "bepsi": "\u03F6",
                "bernou": "\u212C",
                "Bernoullis": "\u212C",
                "Beta": "\u0392",
                "beta": "\u03B2",
                "beth": "\u2136",
                "between": "\u226C",
                "Bfr": "\uD835\uDD05",
                "bfr": "\uD835\uDD1F",
                "bigcap": "\u22C2",
                "bigcirc": "\u25EF",
                "bigcup": "\u22C3",
                "bigodot": "\u2A00",
                "bigoplus": "\u2A01",
                "bigotimes": "\u2A02",
                "bigsqcup": "\u2A06",
                "bigstar": "\u2605",
                "bigtriangledown": "\u25BD",
                "bigtriangleup": "\u25B3",
                "biguplus": "\u2A04",
                "bigvee": "\u22C1",
                "bigwedge": "\u22C0",
                "bkarow": "\u290D",
                "blacklozenge": "\u29EB",
                "blacksquare": "\u25AA",
                "blacktriangle": "\u25B4",
                "blacktriangledown": "\u25BE",
                "blacktriangleleft": "\u25C2",
                "blacktriangleright": "\u25B8",
                "blank": "\u2423",
                "blk12": "\u2592",
                "blk14": "\u2591",
                "blk34": "\u2593",
                "block": "\u2588",
                "bne": "\u003D\u20E5",
                "bnequiv": "\u2261\u20E5",
                "bNot": "\u2AED",
                "bnot": "\u2310",
                "Bopf": "\uD835\uDD39",
                "bopf": "\uD835\uDD53",
                "bot": "\u22A5",
                "bottom": "\u22A5",
                "bowtie": "\u22C8",
                "boxbox": "\u29C9",
                "boxDL": "\u2557",
                "boxDl": "\u2556",
                "boxdL": "\u2555",
                "boxdl": "\u2510",
                "boxDR": "\u2554",
                "boxDr": "\u2553",
                "boxdR": "\u2552",
                "boxdr": "\u250C",
                "boxH": "\u2550",
                "boxh": "\u2500",
                "boxHD": "\u2566",
                "boxHd": "\u2564",
                "boxhD": "\u2565",
                "boxhd": "\u252C",
                "boxHU": "\u2569",
                "boxHu": "\u2567",
                "boxhU": "\u2568",
                "boxhu": "\u2534",
                "boxminus": "\u229F",
                "boxplus": "\u229E",
                "boxtimes": "\u22A0",
                "boxUL": "\u255D",
                "boxUl": "\u255C",
                "boxuL": "\u255B",
                "boxul": "\u2518",
                "boxUR": "\u255A",
                "boxUr": "\u2559",
                "boxuR": "\u2558",
                "boxur": "\u2514",
                "boxV": "\u2551",
                "boxv": "\u2502",
                "boxVH": "\u256C",
                "boxVh": "\u256B",
                "boxvH": "\u256A",
                "boxvh": "\u253C",
                "boxVL": "\u2563",
                "boxVl": "\u2562",
                "boxvL": "\u2561",
                "boxvl": "\u2524",
                "boxVR": "\u2560",
                "boxVr": "\u255F",
                "boxvR": "\u255E",
                "boxvr": "\u251C",
                "bprime": "\u2035",
                "Breve": "\u02D8",
                "breve": "\u02D8",
                "brvbar": "\u00A6",
                "Bscr": "\u212C",
                "bscr": "\uD835\uDCB7",
                "bsemi": "\u204F",
                "bsim": "\u223D",
                "bsime": "\u22CD",
                "bsol": "\u005C",
                "bsolb": "\u29C5",
                "bsolhsub": "\u27C8",
                "bull": "\u2022",
                "bullet": "\u2022",
                "bump": "\u224E",
                "bumpE": "\u2AAE",
                "bumpe": "\u224F",
                "Bumpeq": "\u224E",
                "bumpeq": "\u224F",
                "Cacute": "\u0106",
                "cacute": "\u0107",
                "Cap": "\u22D2",
                "cap": "\u2229",
                "capand": "\u2A44",
                "capbrcup": "\u2A49",
                "capcap": "\u2A4B",
                "capcup": "\u2A47",
                "capdot": "\u2A40",
                "CapitalDifferentialD": "\u2145",
                "caps": "\u2229\uFE00",
                "caret": "\u2041",
                "caron": "\u02C7",
                "Cayleys": "\u212D",
                "ccaps": "\u2A4D",
                "Ccaron": "\u010C",
                "ccaron": "\u010D",
                "Ccedil": "\u00C7",
                "ccedil": "\u00E7",
                "Ccirc": "\u0108",
                "ccirc": "\u0109",
                "Cconint": "\u2230",
                "ccups": "\u2A4C",
                "ccupssm": "\u2A50",
                "Cdot": "\u010A",
                "cdot": "\u010B",
                "cedil": "\u00B8",
                "Cedilla": "\u00B8",
                "cemptyv": "\u29B2",
                "cent": "\u00A2",
                "CenterDot": "\u00B7",
                "centerdot": "\u00B7",
                "Cfr": "\u212D",
                "cfr": "\uD835\uDD20",
                "CHcy": "\u0427",
                "chcy": "\u0447",
                "check": "\u2713",
                "checkmark": "\u2713",
                "Chi": "\u03A7",
                "chi": "\u03C7",
                "cir": "\u25CB",
                "circ": "\u02C6",
                "circeq": "\u2257",
                "circlearrowleft": "\u21BA",
                "circlearrowright": "\u21BB",
                "circledast": "\u229B",
                "circledcirc": "\u229A",
                "circleddash": "\u229D",
                "CircleDot": "\u2299",
                "circledR": "\u00AE",
                "circledS": "\u24C8",
                "CircleMinus": "\u2296",
                "CirclePlus": "\u2295",
                "CircleTimes": "\u2297",
                "cirE": "\u29C3",
                "cire": "\u2257",
                "cirfnint": "\u2A10",
                "cirmid": "\u2AEF",
                "cirscir": "\u29C2",
                "ClockwiseContourIntegral": "\u2232",
                "CloseCurlyDoubleQuote": "\u201D",
                "CloseCurlyQuote": "\u2019",
                "clubs": "\u2663",
                "clubsuit": "\u2663",
                "Colon": "\u2237",
                "colon": "\u003A",
                "Colone": "\u2A74",
                "colone": "\u2254",
                "coloneq": "\u2254",
                "comma": "\u002C",
                "commat": "\u0040",
                "comp": "\u2201",
                "compfn": "\u2218",
                "complement": "\u2201",
                "complexes": "\u2102",
                "cong": "\u2245",
                "congdot": "\u2A6D",
                "Congruent": "\u2261",
                "Conint": "\u222F",
                "conint": "\u222E",
                "ContourIntegral": "\u222E",
                "Copf": "\u2102",
                "copf": "\uD835\uDD54",
                "coprod": "\u2210",
                "Coproduct": "\u2210",
                "COPY": "\u00A9",
                "copy": "\u00A9",
                "copysr": "\u2117",
                "CounterClockwiseContourIntegral": "\u2233",
                "crarr": "\u21B5",
                "Cross": "\u2A2F",
                "cross": "\u2717",
                "Cscr": "\uD835\uDC9E",
                "cscr": "\uD835\uDCB8",
                "csub": "\u2ACF",
                "csube": "\u2AD1",
                "csup": "\u2AD0",
                "csupe": "\u2AD2",
                "ctdot": "\u22EF",
                "cudarrl": "\u2938",
                "cudarrr": "\u2935",
                "cuepr": "\u22DE",
                "cuesc": "\u22DF",
                "cularr": "\u21B6",
                "cularrp": "\u293D",
                "Cup": "\u22D3",
                "cup": "\u222A",
                "cupbrcap": "\u2A48",
                "CupCap": "\u224D",
                "cupcap": "\u2A46",
                "cupcup": "\u2A4A",
                "cupdot": "\u228D",
                "cupor": "\u2A45",
                "cups": "\u222A\uFE00",
                "curarr": "\u21B7",
                "curarrm": "\u293C",
                "curlyeqprec": "\u22DE",
                "curlyeqsucc": "\u22DF",
                "curlyvee": "\u22CE",
                "curlywedge": "\u22CF",
                "curren": "\u00A4",
                "curvearrowleft": "\u21B6",
                "curvearrowright": "\u21B7",
                "cuvee": "\u22CE",
                "cuwed": "\u22CF",
                "cwconint": "\u2232",
                "cwint": "\u2231",
                "cylcty": "\u232D",
                "Dagger": "\u2021",
                "dagger": "\u2020",
                "daleth": "\u2138",
                "Darr": "\u21A1",
                "dArr": "\u21D3",
                "darr": "\u2193",
                "dash": "\u2010",
                "Dashv": "\u2AE4",
                "dashv": "\u22A3",
                "dbkarow": "\u290F",
                "dblac": "\u02DD",
                "Dcaron": "\u010E",
                "dcaron": "\u010F",
                "Dcy": "\u0414",
                "dcy": "\u0434",
                "DD": "\u2145",
                "dd": "\u2146",
                "ddagger": "\u2021",
                "ddarr": "\u21CA",
                "DDotrahd": "\u2911",
                "ddotseq": "\u2A77",
                "deg": "\u00B0",
                "Del": "\u2207",
                "Delta": "\u0394",
                "delta": "\u03B4",
                "demptyv": "\u29B1",
                "dfisht": "\u297F",
                "Dfr": "\uD835\uDD07",
                "dfr": "\uD835\uDD21",
                "dHar": "\u2965",
                "dharl": "\u21C3",
                "dharr": "\u21C2",
                "DiacriticalAcute": "\u00B4",
                "DiacriticalDot": "\u02D9",
                "DiacriticalDoubleAcute": "\u02DD",
                "DiacriticalGrave": "\u0060",
                "DiacriticalTilde": "\u02DC",
                "diam": "\u22C4",
                "Diamond": "\u22C4",
                "diamond": "\u22C4",
                "diamondsuit": "\u2666",
                "diams": "\u2666",
                "die": "\u00A8",
                "DifferentialD": "\u2146",
                "digamma": "\u03DD",
                "disin": "\u22F2",
                "div": "\u00F7",
                "divide": "\u00F7",
                "divideontimes": "\u22C7",
                "divonx": "\u22C7",
                "DJcy": "\u0402",
                "djcy": "\u0452",
                "dlcorn": "\u231E",
                "dlcrop": "\u230D",
                "dollar": "\u0024",
                "Dopf": "\uD835\uDD3B",
                "dopf": "\uD835\uDD55",
                "Dot": "\u00A8",
                "dot": "\u02D9",
                "DotDot": "\u20DC",
                "doteq": "\u2250",
                "doteqdot": "\u2251",
                "DotEqual": "\u2250",
                "dotminus": "\u2238",
                "dotplus": "\u2214",
                "dotsquare": "\u22A1",
                "doublebarwedge": "\u2306",
                "DoubleContourIntegral": "\u222F",
                "DoubleDot": "\u00A8",
                "DoubleDownArrow": "\u21D3",
                "DoubleLeftArrow": "\u21D0",
                "DoubleLeftRightArrow": "\u21D4",
                "DoubleLeftTee": "\u2AE4",
                "DoubleLongLeftArrow": "\u27F8",
                "DoubleLongLeftRightArrow": "\u27FA",
                "DoubleLongRightArrow": "\u27F9",
                "DoubleRightArrow": "\u21D2",
                "DoubleRightTee": "\u22A8",
                "DoubleUpArrow": "\u21D1",
                "DoubleUpDownArrow": "\u21D5",
                "DoubleVerticalBar": "\u2225",
                "DownArrow": "\u2193",
                "Downarrow": "\u21D3",
                "downarrow": "\u2193",
                "DownArrowBar": "\u2913",
                "DownArrowUpArrow": "\u21F5",
                "DownBreve": "\u0311",
                "downdownarrows": "\u21CA",
                "downharpoonleft": "\u21C3",
                "downharpoonright": "\u21C2",
                "DownLeftRightVector": "\u2950",
                "DownLeftTeeVector": "\u295E",
                "DownLeftVector": "\u21BD",
                "DownLeftVectorBar": "\u2956",
                "DownRightTeeVector": "\u295F",
                "DownRightVector": "\u21C1",
                "DownRightVectorBar": "\u2957",
                "DownTee": "\u22A4",
                "DownTeeArrow": "\u21A7",
                "drbkarow": "\u2910",
                "drcorn": "\u231F",
                "drcrop": "\u230C",
                "Dscr": "\uD835\uDC9F",
                "dscr": "\uD835\uDCB9",
                "DScy": "\u0405",
                "dscy": "\u0455",
                "dsol": "\u29F6",
                "Dstrok": "\u0110",
                "dstrok": "\u0111",
                "dtdot": "\u22F1",
                "dtri": "\u25BF",
                "dtrif": "\u25BE",
                "duarr": "\u21F5",
                "duhar": "\u296F",
                "dwangle": "\u29A6",
                "DZcy": "\u040F",
                "dzcy": "\u045F",
                "dzigrarr": "\u27FF",
                "Eacute": "\u00C9",
                "eacute": "\u00E9",
                "easter": "\u2A6E",
                "Ecaron": "\u011A",
                "ecaron": "\u011B",
                "ecir": "\u2256",
                "Ecirc": "\u00CA",
                "ecirc": "\u00EA",
                "ecolon": "\u2255",
                "Ecy": "\u042D",
                "ecy": "\u044D",
                "eDDot": "\u2A77",
                "Edot": "\u0116",
                "eDot": "\u2251",
                "edot": "\u0117",
                "ee": "\u2147",
                "efDot": "\u2252",
                "Efr": "\uD835\uDD08",
                "efr": "\uD835\uDD22",
                "eg": "\u2A9A",
                "Egrave": "\u00C8",
                "egrave": "\u00E8",
                "egs": "\u2A96",
                "egsdot": "\u2A98",
                "el": "\u2A99",
                "Element": "\u2208",
                "elinters": "\u23E7",
                "ell": "\u2113",
                "els": "\u2A95",
                "elsdot": "\u2A97",
                "Emacr": "\u0112",
                "emacr": "\u0113",
                "empty": "\u2205",
                "emptyset": "\u2205",
                "EmptySmallSquare": "\u25FB",
                "emptyv": "\u2205",
                "EmptyVerySmallSquare": "\u25AB",
                "emsp": "\u2003",
                "emsp13": "\u2004",
                "emsp14": "\u2005",
                "ENG": "\u014A",
                "eng": "\u014B",
                "ensp": "\u2002",
                "Eogon": "\u0118",
                "eogon": "\u0119",
                "Eopf": "\uD835\uDD3C",
                "eopf": "\uD835\uDD56",
                "epar": "\u22D5",
                "eparsl": "\u29E3",
                "eplus": "\u2A71",
                "epsi": "\u03B5",
                "Epsilon": "\u0395",
                "epsilon": "\u03B5",
                "epsiv": "\u03F5",
                "eqcirc": "\u2256",
                "eqcolon": "\u2255",
                "eqsim": "\u2242",
                "eqslantgtr": "\u2A96",
                "eqslantless": "\u2A95",
                "Equal": "\u2A75",
                "equals": "\u003D",
                "EqualTilde": "\u2242",
                "equest": "\u225F",
                "Equilibrium": "\u21CC",
                "equiv": "\u2261",
                "equivDD": "\u2A78",
                "eqvparsl": "\u29E5",
                "erarr": "\u2971",
                "erDot": "\u2253",
                "Escr": "\u2130",
                "escr": "\u212F",
                "esdot": "\u2250",
                "Esim": "\u2A73",
                "esim": "\u2242",
                "Eta": "\u0397",
                "eta": "\u03B7",
                "ETH": "\u00D0",
                "eth": "\u00F0",
                "Euml": "\u00CB",
                "euml": "\u00EB",
                "euro": "\u20AC",
                "excl": "\u0021",
                "exist": "\u2203",
                "Exists": "\u2203",
                "expectation": "\u2130",
                "ExponentialE": "\u2147",
                "exponentiale": "\u2147",
                "fallingdotseq": "\u2252",
                "Fcy": "\u0424",
                "fcy": "\u0444",
                "female": "\u2640",
                "ffilig": "\uFB03",
                "fflig": "\uFB00",
                "ffllig": "\uFB04",
                "Ffr": "\uD835\uDD09",
                "ffr": "\uD835\uDD23",
                "filig": "\uFB01",
                "FilledSmallSquare": "\u25FC",
                "FilledVerySmallSquare": "\u25AA",
                "fjlig": "\u0066\u006A",
                "flat": "\u266D",
                "fllig": "\uFB02",
                "fltns": "\u25B1",
                "fnof": "\u0192",
                "Fopf": "\uD835\uDD3D",
                "fopf": "\uD835\uDD57",
                "ForAll": "\u2200",
                "forall": "\u2200",
                "fork": "\u22D4",
                "forkv": "\u2AD9",
                "Fouriertrf": "\u2131",
                "fpartint": "\u2A0D",
                "frac12": "\u00BD",
                "frac13": "\u2153",
                "frac14": "\u00BC",
                "frac15": "\u2155",
                "frac16": "\u2159",
                "frac18": "\u215B",
                "frac23": "\u2154",
                "frac25": "\u2156",
                "frac34": "\u00BE",
                "frac35": "\u2157",
                "frac38": "\u215C",
                "frac45": "\u2158",
                "frac56": "\u215A",
                "frac58": "\u215D",
                "frac78": "\u215E",
                "frasl": "\u2044",
                "frown": "\u2322",
                "Fscr": "\u2131",
                "fscr": "\uD835\uDCBB",
                "gacute": "\u01F5",
                "Gamma": "\u0393",
                "gamma": "\u03B3",
                "Gammad": "\u03DC",
                "gammad": "\u03DD",
                "gap": "\u2A86",
                "Gbreve": "\u011E",
                "gbreve": "\u011F",
                "Gcedil": "\u0122",
                "Gcirc": "\u011C",
                "gcirc": "\u011D",
                "Gcy": "\u0413",
                "gcy": "\u0433",
                "Gdot": "\u0120",
                "gdot": "\u0121",
                "gE": "\u2267",
                "ge": "\u2265",
                "gEl": "\u2A8C",
                "gel": "\u22DB",
                "geq": "\u2265",
                "geqq": "\u2267",
                "geqslant": "\u2A7E",
                "ges": "\u2A7E",
                "gescc": "\u2AA9",
                "gesdot": "\u2A80",
                "gesdoto": "\u2A82",
                "gesdotol": "\u2A84",
                "gesl": "\u22DB\uFE00",
                "gesles": "\u2A94",
                "Gfr": "\uD835\uDD0A",
                "gfr": "\uD835\uDD24",
                "Gg": "\u22D9",
                "gg": "\u226B",
                "ggg": "\u22D9",
                "gimel": "\u2137",
                "GJcy": "\u0403",
                "gjcy": "\u0453",
                "gl": "\u2277",
                "gla": "\u2AA5",
                "glE": "\u2A92",
                "glj": "\u2AA4",
                "gnap": "\u2A8A",
                "gnapprox": "\u2A8A",
                "gnE": "\u2269",
                "gne": "\u2A88",
                "gneq": "\u2A88",
                "gneqq": "\u2269",
                "gnsim": "\u22E7",
                "Gopf": "\uD835\uDD3E",
                "gopf": "\uD835\uDD58",
                "grave": "\u0060",
                "GreaterEqual": "\u2265",
                "GreaterEqualLess": "\u22DB",
                "GreaterFullEqual": "\u2267",
                "GreaterGreater": "\u2AA2",
                "GreaterLess": "\u2277",
                "GreaterSlantEqual": "\u2A7E",
                "GreaterTilde": "\u2273",
                "Gscr": "\uD835\uDCA2",
                "gscr": "\u210A",
                "gsim": "\u2273",
                "gsime": "\u2A8E",
                "gsiml": "\u2A90",
                "GT": "\u003E",
                "Gt": "\u226B",
                "gt": "\u003E",
                "gtcc": "\u2AA7",
                "gtcir": "\u2A7A",
                "gtdot": "\u22D7",
                "gtlPar": "\u2995",
                "gtquest": "\u2A7C",
                "gtrapprox": "\u2A86",
                "gtrarr": "\u2978",
                "gtrdot": "\u22D7",
                "gtreqless": "\u22DB",
                "gtreqqless": "\u2A8C",
                "gtrless": "\u2277",
                "gtrsim": "\u2273",
                "gvertneqq": "\u2269\uFE00",
                "gvnE": "\u2269\uFE00",
                "Hacek": "\u02C7",
                "hairsp": "\u200A",
                "half": "\u00BD",
                "hamilt": "\u210B",
                "HARDcy": "\u042A",
                "hardcy": "\u044A",
                "hArr": "\u21D4",
                "harr": "\u2194",
                "harrcir": "\u2948",
                "harrw": "\u21AD",
                "Hat": "\u005E",
                "hbar": "\u210F",
                "Hcirc": "\u0124",
                "hcirc": "\u0125",
                "hearts": "\u2665",
                "heartsuit": "\u2665",
                "hellip": "\u2026",
                "hercon": "\u22B9",
                "Hfr": "\u210C",
                "hfr": "\uD835\uDD25",
                "HilbertSpace": "\u210B",
                "hksearow": "\u2925",
                "hkswarow": "\u2926",
                "hoarr": "\u21FF",
                "homtht": "\u223B",
                "hookleftarrow": "\u21A9",
                "hookrightarrow": "\u21AA",
                "Hopf": "\u210D",
                "hopf": "\uD835\uDD59",
                "horbar": "\u2015",
                "HorizontalLine": "\u2500",
                "Hscr": "\u210B",
                "hscr": "\uD835\uDCBD",
                "hslash": "\u210F",
                "Hstrok": "\u0126",
                "hstrok": "\u0127",
                "HumpDownHump": "\u224E",
                "HumpEqual": "\u224F",
                "hybull": "\u2043",
                "hyphen": "\u2010",
                "Iacute": "\u00CD",
                "iacute": "\u00ED",
                "ic": "\u2063",
                "Icirc": "\u00CE",
                "icirc": "\u00EE",
                "Icy": "\u0418",
                "icy": "\u0438",
                "Idot": "\u0130",
                "IEcy": "\u0415",
                "iecy": "\u0435",
                "iexcl": "\u00A1",
                "iff": "\u21D4",
                "Ifr": "\u2111",
                "ifr": "\uD835\uDD26",
                "Igrave": "\u00CC",
                "igrave": "\u00EC",
                "ii": "\u2148",
                "iiiint": "\u2A0C",
                "iiint": "\u222D",
                "iinfin": "\u29DC",
                "iiota": "\u2129",
                "IJlig": "\u0132",
                "ijlig": "\u0133",
                "Im": "\u2111",
                "Imacr": "\u012A",
                "imacr": "\u012B",
                "image": "\u2111",
                "ImaginaryI": "\u2148",
                "imagline": "\u2110",
                "imagpart": "\u2111",
                "imath": "\u0131",
                "imof": "\u22B7",
                "imped": "\u01B5",
                "Implies": "\u21D2",
                "in": "\u2208",
                "incare": "\u2105",
                "infin": "\u221E",
                "infintie": "\u29DD",
                "inodot": "\u0131",
                "Int": "\u222C",
                "int": "\u222B",
                "intcal": "\u22BA",
                "integers": "\u2124",
                "Integral": "\u222B",
                "intercal": "\u22BA",
                "Intersection": "\u22C2",
                "intlarhk": "\u2A17",
                "intprod": "\u2A3C",
                "InvisibleComma": "\u2063",
                "InvisibleTimes": "\u2062",
                "IOcy": "\u0401",
                "iocy": "\u0451",
                "Iogon": "\u012E",
                "iogon": "\u012F",
                "Iopf": "\uD835\uDD40",
                "iopf": "\uD835\uDD5A",
                "Iota": "\u0399",
                "iota": "\u03B9",
                "iprod": "\u2A3C",
                "iquest": "\u00BF",
                "Iscr": "\u2110",
                "iscr": "\uD835\uDCBE",
                "isin": "\u2208",
                "isindot": "\u22F5",
                "isinE": "\u22F9",
                "isins": "\u22F4",
                "isinsv": "\u22F3",
                "isinv": "\u2208",
                "it": "\u2062",
                "Itilde": "\u0128",
                "itilde": "\u0129",
                "Iukcy": "\u0406",
                "iukcy": "\u0456",
                "Iuml": "\u00CF",
                "iuml": "\u00EF",
                "Jcirc": "\u0134",
                "jcirc": "\u0135",
                "Jcy": "\u0419",
                "jcy": "\u0439",
                "Jfr": "\uD835\uDD0D",
                "jfr": "\uD835\uDD27",
                "jmath": "\u0237",
                "Jopf": "\uD835\uDD41",
                "jopf": "\uD835\uDD5B",
                "Jscr": "\uD835\uDCA5",
                "jscr": "\uD835\uDCBF",
                "Jsercy": "\u0408",
                "jsercy": "\u0458",
                "Jukcy": "\u0404",
                "jukcy": "\u0454",
                "Kappa": "\u039A",
                "kappa": "\u03BA",
                "kappav": "\u03F0",
                "Kcedil": "\u0136",
                "kcedil": "\u0137",
                "Kcy": "\u041A",
                "kcy": "\u043A",
                "Kfr": "\uD835\uDD0E",
                "kfr": "\uD835\uDD28",
                "kgreen": "\u0138",
                "KHcy": "\u0425",
                "khcy": "\u0445",
                "KJcy": "\u040C",
                "kjcy": "\u045C",
                "Kopf": "\uD835\uDD42",
                "kopf": "\uD835\uDD5C",
                "Kscr": "\uD835\uDCA6",
                "kscr": "\uD835\uDCC0",
                "lAarr": "\u21DA",
                "Lacute": "\u0139",
                "lacute": "\u013A",
                "laemptyv": "\u29B4",
                "lagran": "\u2112",
                "Lambda": "\u039B",
                "lambda": "\u03BB",
                "Lang": "\u27EA",
                "lang": "\u27E8",
                "langd": "\u2991",
                "langle": "\u27E8",
                "lap": "\u2A85",
                "Laplacetrf": "\u2112",
                "laquo": "\u00AB",
                "Larr": "\u219E",
                "lArr": "\u21D0",
                "larr": "\u2190",
                "larrb": "\u21E4",
                "larrbfs": "\u291F",
                "larrfs": "\u291D",
                "larrhk": "\u21A9",
                "larrlp": "\u21AB",
                "larrpl": "\u2939",
                "larrsim": "\u2973",
                "larrtl": "\u21A2",
                "lat": "\u2AAB",
                "lAtail": "\u291B",
                "latail": "\u2919",
                "late": "\u2AAD",
                "lates": "\u2AAD\uFE00",
                "lBarr": "\u290E",
                "lbarr": "\u290C",
                "lbbrk": "\u2772",
                "lbrace": "\u007B",
                "lbrack": "\u005B",
                "lbrke": "\u298B",
                "lbrksld": "\u298F",
                "lbrkslu": "\u298D",
                "Lcaron": "\u013D",
                "lcaron": "\u013E",
                "Lcedil": "\u013B",
                "lcedil": "\u013C",
                "lceil": "\u2308",
                "lcub": "\u007B",
                "Lcy": "\u041B",
                "lcy": "\u043B",
                "ldca": "\u2936",
                "ldquo": "\u201C",
                "ldquor": "\u201E",
                "ldrdhar": "\u2967",
                "ldrushar": "\u294B",
                "ldsh": "\u21B2",
                "lE": "\u2266",
                "le": "\u2264",
                "LeftAngleBracket": "\u27E8",
                "LeftArrow": "\u2190",
                "Leftarrow": "\u21D0",
                "leftarrow": "\u2190",
                "LeftArrowBar": "\u21E4",
                "LeftArrowRightArrow": "\u21C6",
                "leftarrowtail": "\u21A2",
                "LeftCeiling": "\u2308",
                "LeftDoubleBracket": "\u27E6",
                "LeftDownTeeVector": "\u2961",
                "LeftDownVector": "\u21C3",
                "LeftDownVectorBar": "\u2959",
                "LeftFloor": "\u230A",
                "leftharpoondown": "\u21BD",
                "leftharpoonup": "\u21BC",
                "leftleftarrows": "\u21C7",
                "LeftRightArrow": "\u2194",
                "Leftrightarrow": "\u21D4",
                "leftrightarrow": "\u2194",
                "leftrightarrows": "\u21C6",
                "leftrightharpoons": "\u21CB",
                "leftrightsquigarrow": "\u21AD",
                "LeftRightVector": "\u294E",
                "LeftTee": "\u22A3",
                "LeftTeeArrow": "\u21A4",
                "LeftTeeVector": "\u295A",
                "leftthreetimes": "\u22CB",
                "LeftTriangle": "\u22B2",
                "LeftTriangleBar": "\u29CF",
                "LeftTriangleEqual": "\u22B4",
                "LeftUpDownVector": "\u2951",
                "LeftUpTeeVector": "\u2960",
                "LeftUpVector": "\u21BF",
                "LeftUpVectorBar": "\u2958",
                "LeftVector": "\u21BC",
                "LeftVectorBar": "\u2952",
                "lEg": "\u2A8B",
                "leg": "\u22DA",
                "leq": "\u2264",
                "leqq": "\u2266",
                "leqslant": "\u2A7D",
                "les": "\u2A7D",
                "lescc": "\u2AA8",
                "lesdot": "\u2A7F",
                "lesdoto": "\u2A81",
                "lesdotor": "\u2A83",
                "lesg": "\u22DA\uFE00",
                "lesges": "\u2A93",
                "lessapprox": "\u2A85",
                "lessdot": "\u22D6",
                "lesseqgtr": "\u22DA",
                "lesseqqgtr": "\u2A8B",
                "LessEqualGreater": "\u22DA",
                "LessFullEqual": "\u2266",
                "LessGreater": "\u2276",
                "lessgtr": "\u2276",
                "LessLess": "\u2AA1",
                "lesssim": "\u2272",
                "LessSlantEqual": "\u2A7D",
                "LessTilde": "\u2272",
                "lfisht": "\u297C",
                "lfloor": "\u230A",
                "Lfr": "\uD835\uDD0F",
                "lfr": "\uD835\uDD29",
                "lg": "\u2276",
                "lgE": "\u2A91",
                "lHar": "\u2962",
                "lhard": "\u21BD",
                "lharu": "\u21BC",
                "lharul": "\u296A",
                "lhblk": "\u2584",
                "LJcy": "\u0409",
                "ljcy": "\u0459",
                "Ll": "\u22D8",
                "ll": "\u226A",
                "llarr": "\u21C7",
                "llcorner": "\u231E",
                "Lleftarrow": "\u21DA",
                "llhard": "\u296B",
                "lltri": "\u25FA",
                "Lmidot": "\u013F",
                "lmidot": "\u0140",
                "lmoust": "\u23B0",
                "lmoustache": "\u23B0",
                "lnap": "\u2A89",
                "lnapprox": "\u2A89",
                "lnE": "\u2268",
                "lne": "\u2A87",
                "lneq": "\u2A87",
                "lneqq": "\u2268",
                "lnsim": "\u22E6",
                "loang": "\u27EC",
                "loarr": "\u21FD",
                "lobrk": "\u27E6",
                "LongLeftArrow": "\u27F5",
                "Longleftarrow": "\u27F8",
                "longleftarrow": "\u27F5",
                "LongLeftRightArrow": "\u27F7",
                "Longleftrightarrow": "\u27FA",
                "longleftrightarrow": "\u27F7",
                "longmapsto": "\u27FC",
                "LongRightArrow": "\u27F6",
                "Longrightarrow": "\u27F9",
                "longrightarrow": "\u27F6",
                "looparrowleft": "\u21AB",
                "looparrowright": "\u21AC",
                "lopar": "\u2985",
                "Lopf": "\uD835\uDD43",
                "lopf": "\uD835\uDD5D",
                "loplus": "\u2A2D",
                "lotimes": "\u2A34",
                "lowast": "\u2217",
                "lowbar": "\u005F",
                "LowerLeftArrow": "\u2199",
                "LowerRightArrow": "\u2198",
                "loz": "\u25CA",
                "lozenge": "\u25CA",
                "lozf": "\u29EB",
                "lpar": "\u0028",
                "lparlt": "\u2993",
                "lrarr": "\u21C6",
                "lrcorner": "\u231F",
                "lrhar": "\u21CB",
                "lrhard": "\u296D",
                "lrm": "\u200E",
                "lrtri": "\u22BF",
                "lsaquo": "\u2039",
                "Lscr": "\u2112",
                "lscr": "\uD835\uDCC1",
                "Lsh": "\u21B0",
                "lsh": "\u21B0",
                "lsim": "\u2272",
                "lsime": "\u2A8D",
                "lsimg": "\u2A8F",
                "lsqb": "\u005B",
                "lsquo": "\u2018",
                "lsquor": "\u201A",
                "Lstrok": "\u0141",
                "lstrok": "\u0142",
                "LT": "\u003C",
                "Lt": "\u226A",
                "lt": "\u003C",
                "ltcc": "\u2AA6",
                "ltcir": "\u2A79",
                "ltdot": "\u22D6",
                "lthree": "\u22CB",
                "ltimes": "\u22C9",
                "ltlarr": "\u2976",
                "ltquest": "\u2A7B",
                "ltri": "\u25C3",
                "ltrie": "\u22B4",
                "ltrif": "\u25C2",
                "ltrPar": "\u2996",
                "lurdshar": "\u294A",
                "luruhar": "\u2966",
                "lvertneqq": "\u2268\uFE00",
                "lvnE": "\u2268\uFE00",
                "macr": "\u00AF",
                "male": "\u2642",
                "malt": "\u2720",
                "maltese": "\u2720",
                "Map": "\u2905",
                "map": "\u21A6",
                "mapsto": "\u21A6",
                "mapstodown": "\u21A7",
                "mapstoleft": "\u21A4",
                "mapstoup": "\u21A5",
                "marker": "\u25AE",
                "mcomma": "\u2A29",
                "Mcy": "\u041C",
                "mcy": "\u043C",
                "mdash": "\u2014",
                "mDDot": "\u223A",
                "measuredangle": "\u2221",
                "MediumSpace": "\u205F",
                "Mellintrf": "\u2133",
                "Mfr": "\uD835\uDD10",
                "mfr": "\uD835\uDD2A",
                "mho": "\u2127",
                "micro": "\u00B5",
                "mid": "\u2223",
                "midast": "\u002A",
                "midcir": "\u2AF0",
                "middot": "\u00B7",
                "minus": "\u2212",
                "minusb": "\u229F",
                "minusd": "\u2238",
                "minusdu": "\u2A2A",
                "MinusPlus": "\u2213",
                "mlcp": "\u2ADB",
                "mldr": "\u2026",
                "mnplus": "\u2213",
                "models": "\u22A7",
                "Mopf": "\uD835\uDD44",
                "mopf": "\uD835\uDD5E",
                "mp": "\u2213",
                "Mscr": "\u2133",
                "mscr": "\uD835\uDCC2",
                "mstpos": "\u223E",
                "Mu": "\u039C",
                "mu": "\u03BC",
                "multimap": "\u22B8",
                "mumap": "\u22B8",
                "nabla": "\u2207",
                "Nacute": "\u0143",
                "nacute": "\u0144",
                "nang": "\u2220\u20D2",
                "nap": "\u2249",
                "napE": "\u2A70\u0338",
                "napid": "\u224B\u0338",
                "napos": "\u0149",
                "napprox": "\u2249",
                "natur": "\u266E",
                "natural": "\u266E",
                "naturals": "\u2115",
                "nbsp": "\u00A0",
                "nbump": "\u224E\u0338",
                "nbumpe": "\u224F\u0338",
                "ncap": "\u2A43",
                "Ncaron": "\u0147",
                "ncaron": "\u0148",
                "Ncedil": "\u0145",
                "ncedil": "\u0146",
                "ncong": "\u2247",
                "ncongdot": "\u2A6D\u0338",
                "ncup": "\u2A42",
                "Ncy": "\u041D",
                "ncy": "\u043D",
                "ndash": "\u2013",
                "ne": "\u2260",
                "nearhk": "\u2924",
                "neArr": "\u21D7",
                "nearr": "\u2197",
                "nearrow": "\u2197",
                "nedot": "\u2250\u0338",
                "NegativeMediumSpace": "\u200B",
                "NegativeThickSpace": "\u200B",
                "NegativeThinSpace": "\u200B",
                "NegativeVeryThinSpace": "\u200B",
                "nequiv": "\u2262",
                "nesear": "\u2928",
                "nesim": "\u2242\u0338",
                "NestedGreaterGreater": "\u226B",
                "NestedLessLess": "\u226A",
                "NewLine": "\u000A",
                "nexist": "\u2204",
                "nexists": "\u2204",
                "Nfr": "\uD835\uDD11",
                "nfr": "\uD835\uDD2B",
                "ngE": "\u2267\u0338",
                "nge": "\u2271",
                "ngeq": "\u2271",
                "ngeqq": "\u2267\u0338",
                "ngeqslant": "\u2A7E\u0338",
                "nges": "\u2A7E\u0338",
                "nGg": "\u22D9\u0338",
                "ngsim": "\u2275",
                "nGt": "\u226B\u20D2",
                "ngt": "\u226F",
                "ngtr": "\u226F",
                "nGtv": "\u226B\u0338",
                "nhArr": "\u21CE",
                "nharr": "\u21AE",
                "nhpar": "\u2AF2",
                "ni": "\u220B",
                "nis": "\u22FC",
                "nisd": "\u22FA",
                "niv": "\u220B",
                "NJcy": "\u040A",
                "njcy": "\u045A",
                "nlArr": "\u21CD",
                "nlarr": "\u219A",
                "nldr": "\u2025",
                "nlE": "\u2266\u0338",
                "nle": "\u2270",
                "nLeftarrow": "\u21CD",
                "nleftarrow": "\u219A",
                "nLeftrightarrow": "\u21CE",
                "nleftrightarrow": "\u21AE",
                "nleq": "\u2270",
                "nleqq": "\u2266\u0338",
                "nleqslant": "\u2A7D\u0338",
                "nles": "\u2A7D\u0338",
                "nless": "\u226E",
                "nLl": "\u22D8\u0338",
                "nlsim": "\u2274",
                "nLt": "\u226A\u20D2",
                "nlt": "\u226E",
                "nltri": "\u22EA",
                "nltrie": "\u22EC",
                "nLtv": "\u226A\u0338",
                "nmid": "\u2224",
                "NoBreak": "\u2060",
                "NonBreakingSpace": "\u00A0",
                "Nopf": "\u2115",
                "nopf": "\uD835\uDD5F",
                "Not": "\u2AEC",
                "not": "\u00AC",
                "NotCongruent": "\u2262",
                "NotCupCap": "\u226D",
                "NotDoubleVerticalBar": "\u2226",
                "NotElement": "\u2209",
                "NotEqual": "\u2260",
                "NotEqualTilde": "\u2242\u0338",
                "NotExists": "\u2204",
                "NotGreater": "\u226F",
                "NotGreaterEqual": "\u2271",
                "NotGreaterFullEqual": "\u2267\u0338",
                "NotGreaterGreater": "\u226B\u0338",
                "NotGreaterLess": "\u2279",
                "NotGreaterSlantEqual": "\u2A7E\u0338",
                "NotGreaterTilde": "\u2275",
                "NotHumpDownHump": "\u224E\u0338",
                "NotHumpEqual": "\u224F\u0338",
                "notin": "\u2209",
                "notindot": "\u22F5\u0338",
                "notinE": "\u22F9\u0338",
                "notinva": "\u2209",
                "notinvb": "\u22F7",
                "notinvc": "\u22F6",
                "NotLeftTriangle": "\u22EA",
                "NotLeftTriangleBar": "\u29CF\u0338",
                "NotLeftTriangleEqual": "\u22EC",
                "NotLess": "\u226E",
                "NotLessEqual": "\u2270",
                "NotLessGreater": "\u2278",
                "NotLessLess": "\u226A\u0338",
                "NotLessSlantEqual": "\u2A7D\u0338",
                "NotLessTilde": "\u2274",
                "NotNestedGreaterGreater": "\u2AA2\u0338",
                "NotNestedLessLess": "\u2AA1\u0338",
                "notni": "\u220C",
                "notniva": "\u220C",
                "notnivb": "\u22FE",
                "notnivc": "\u22FD",
                "NotPrecedes": "\u2280",
                "NotPrecedesEqual": "\u2AAF\u0338",
                "NotPrecedesSlantEqual": "\u22E0",
                "NotReverseElement": "\u220C",
                "NotRightTriangle": "\u22EB",
                "NotRightTriangleBar": "\u29D0\u0338",
                "NotRightTriangleEqual": "\u22ED",
                "NotSquareSubset": "\u228F\u0338",
                "NotSquareSubsetEqual": "\u22E2",
                "NotSquareSuperset": "\u2290\u0338",
                "NotSquareSupersetEqual": "\u22E3",
                "NotSubset": "\u2282\u20D2",
                "NotSubsetEqual": "\u2288",
                "NotSucceeds": "\u2281",
                "NotSucceedsEqual": "\u2AB0\u0338",
                "NotSucceedsSlantEqual": "\u22E1",
                "NotSucceedsTilde": "\u227F\u0338",
                "NotSuperset": "\u2283\u20D2",
                "NotSupersetEqual": "\u2289",
                "NotTilde": "\u2241",
                "NotTildeEqual": "\u2244",
                "NotTildeFullEqual": "\u2247",
                "NotTildeTilde": "\u2249",
                "NotVerticalBar": "\u2224",
                "npar": "\u2226",
                "nparallel": "\u2226",
                "nparsl": "\u2AFD\u20E5",
                "npart": "\u2202\u0338",
                "npolint": "\u2A14",
                "npr": "\u2280",
                "nprcue": "\u22E0",
                "npre": "\u2AAF\u0338",
                "nprec": "\u2280",
                "npreceq": "\u2AAF\u0338",
                "nrArr": "\u21CF",
                "nrarr": "\u219B",
                "nrarrc": "\u2933\u0338",
                "nrarrw": "\u219D\u0338",
                "nRightarrow": "\u21CF",
                "nrightarrow": "\u219B",
                "nrtri": "\u22EB",
                "nrtrie": "\u22ED",
                "nsc": "\u2281",
                "nsccue": "\u22E1",
                "nsce": "\u2AB0\u0338",
                "Nscr": "\uD835\uDCA9",
                "nscr": "\uD835\uDCC3",
                "nshortmid": "\u2224",
                "nshortparallel": "\u2226",
                "nsim": "\u2241",
                "nsime": "\u2244",
                "nsimeq": "\u2244",
                "nsmid": "\u2224",
                "nspar": "\u2226",
                "nsqsube": "\u22E2",
                "nsqsupe": "\u22E3",
                "nsub": "\u2284",
                "nsubE": "\u2AC5\u0338",
                "nsube": "\u2288",
                "nsubset": "\u2282\u20D2",
                "nsubseteq": "\u2288",
                "nsubseteqq": "\u2AC5\u0338",
                "nsucc": "\u2281",
                "nsucceq": "\u2AB0\u0338",
                "nsup": "\u2285",
                "nsupE": "\u2AC6\u0338",
                "nsupe": "\u2289",
                "nsupset": "\u2283\u20D2",
                "nsupseteq": "\u2289",
                "nsupseteqq": "\u2AC6\u0338",
                "ntgl": "\u2279",
                "Ntilde": "\u00D1",
                "ntilde": "\u00F1",
                "ntlg": "\u2278",
                "ntriangleleft": "\u22EA",
                "ntrianglelefteq": "\u22EC",
                "ntriangleright": "\u22EB",
                "ntrianglerighteq": "\u22ED",
                "Nu": "\u039D",
                "nu": "\u03BD",
                "num": "\u0023",
                "numero": "\u2116",
                "numsp": "\u2007",
                "nvap": "\u224D\u20D2",
                "nVDash": "\u22AF",
                "nVdash": "\u22AE",
                "nvDash": "\u22AD",
                "nvdash": "\u22AC",
                "nvge": "\u2265\u20D2",
                "nvgt": "\u003E\u20D2",
                "nvHarr": "\u2904",
                "nvinfin": "\u29DE",
                "nvlArr": "\u2902",
                "nvle": "\u2264\u20D2",
                "nvlt": "\u003C\u20D2",
                "nvltrie": "\u22B4\u20D2",
                "nvrArr": "\u2903",
                "nvrtrie": "\u22B5\u20D2",
                "nvsim": "\u223C\u20D2",
                "nwarhk": "\u2923",
                "nwArr": "\u21D6",
                "nwarr": "\u2196",
                "nwarrow": "\u2196",
                "nwnear": "\u2927",
                "Oacute": "\u00D3",
                "oacute": "\u00F3",
                "oast": "\u229B",
                "ocir": "\u229A",
                "Ocirc": "\u00D4",
                "ocirc": "\u00F4",
                "Ocy": "\u041E",
                "ocy": "\u043E",
                "odash": "\u229D",
                "Odblac": "\u0150",
                "odblac": "\u0151",
                "odiv": "\u2A38",
                "odot": "\u2299",
                "odsold": "\u29BC",
                "OElig": "\u0152",
                "oelig": "\u0153",
                "ofcir": "\u29BF",
                "Ofr": "\uD835\uDD12",
                "ofr": "\uD835\uDD2C",
                "ogon": "\u02DB",
                "Ograve": "\u00D2",
                "ograve": "\u00F2",
                "ogt": "\u29C1",
                "ohbar": "\u29B5",
                "ohm": "\u03A9",
                "oint": "\u222E",
                "olarr": "\u21BA",
                "olcir": "\u29BE",
                "olcross": "\u29BB",
                "oline": "\u203E",
                "olt": "\u29C0",
                "Omacr": "\u014C",
                "omacr": "\u014D",
                "Omega": "\u03A9",
                "omega": "\u03C9",
                "Omicron": "\u039F",
                "omicron": "\u03BF",
                "omid": "\u29B6",
                "ominus": "\u2296",
                "Oopf": "\uD835\uDD46",
                "oopf": "\uD835\uDD60",
                "opar": "\u29B7",
                "OpenCurlyDoubleQuote": "\u201C",
                "OpenCurlyQuote": "\u2018",
                "operp": "\u29B9",
                "oplus": "\u2295",
                "Or": "\u2A54",
                "or": "\u2228",
                "orarr": "\u21BB",
                "ord": "\u2A5D",
                "order": "\u2134",
                "orderof": "\u2134",
                "ordf": "\u00AA",
                "ordm": "\u00BA",
                "origof": "\u22B6",
                "oror": "\u2A56",
                "orslope": "\u2A57",
                "orv": "\u2A5B",
                "oS": "\u24C8",
                "Oscr": "\uD835\uDCAA",
                "oscr": "\u2134",
                "Oslash": "\u00D8",
                "oslash": "\u00F8",
                "osol": "\u2298",
                "Otilde": "\u00D5",
                "otilde": "\u00F5",
                "Otimes": "\u2A37",
                "otimes": "\u2297",
                "otimesas": "\u2A36",
                "Ouml": "\u00D6",
                "ouml": "\u00F6",
                "ovbar": "\u233D",
                "OverBar": "\u203E",
                "OverBrace": "\u23DE",
                "OverBracket": "\u23B4",
                "OverParenthesis": "\u23DC",
                "par": "\u2225",
                "para": "\u00B6",
                "parallel": "\u2225",
                "parsim": "\u2AF3",
                "parsl": "\u2AFD",
                "part": "\u2202",
                "PartialD": "\u2202",
                "Pcy": "\u041F",
                "pcy": "\u043F",
                "percnt": "\u0025",
                "period": "\u002E",
                "permil": "\u2030",
                "perp": "\u22A5",
                "pertenk": "\u2031",
                "Pfr": "\uD835\uDD13",
                "pfr": "\uD835\uDD2D",
                "Phi": "\u03A6",
                "phi": "\u03C6",
                "phiv": "\u03D5",
                "phmmat": "\u2133",
                "phone": "\u260E",
                "Pi": "\u03A0",
                "pi": "\u03C0",
                "pitchfork": "\u22D4",
                "piv": "\u03D6",
                "planck": "\u210F",
                "planckh": "\u210E",
                "plankv": "\u210F",
                "plus": "\u002B",
                "plusacir": "\u2A23",
                "plusb": "\u229E",
                "pluscir": "\u2A22",
                "plusdo": "\u2214",
                "plusdu": "\u2A25",
                "pluse": "\u2A72",
                "PlusMinus": "\u00B1",
                "plusmn": "\u00B1",
                "plussim": "\u2A26",
                "plustwo": "\u2A27",
                "pm": "\u00B1",
                "Poincareplane": "\u210C",
                "pointint": "\u2A15",
                "Popf": "\u2119",
                "popf": "\uD835\uDD61",
                "pound": "\u00A3",
                "Pr": "\u2ABB",
                "pr": "\u227A",
                "prap": "\u2AB7",
                "prcue": "\u227C",
                "prE": "\u2AB3",
                "pre": "\u2AAF",
                "prec": "\u227A",
                "precapprox": "\u2AB7",
                "preccurlyeq": "\u227C",
                "Precedes": "\u227A",
                "PrecedesEqual": "\u2AAF",
                "PrecedesSlantEqual": "\u227C",
                "PrecedesTilde": "\u227E",
                "preceq": "\u2AAF",
                "precnapprox": "\u2AB9",
                "precneqq": "\u2AB5",
                "precnsim": "\u22E8",
                "precsim": "\u227E",
                "Prime": "\u2033",
                "prime": "\u2032",
                "primes": "\u2119",
                "prnap": "\u2AB9",
                "prnE": "\u2AB5",
                "prnsim": "\u22E8",
                "prod": "\u220F",
                "Product": "\u220F",
                "profalar": "\u232E",
                "profline": "\u2312",
                "profsurf": "\u2313",
                "prop": "\u221D",
                "Proportion": "\u2237",
                "Proportional": "\u221D",
                "propto": "\u221D",
                "prsim": "\u227E",
                "prurel": "\u22B0",
                "Pscr": "\uD835\uDCAB",
                "pscr": "\uD835\uDCC5",
                "Psi": "\u03A8",
                "psi": "\u03C8",
                "puncsp": "\u2008",
                "Qfr": "\uD835\uDD14",
                "qfr": "\uD835\uDD2E",
                "qint": "\u2A0C",
                "Qopf": "\u211A",
                "qopf": "\uD835\uDD62",
                "qprime": "\u2057",
                "Qscr": "\uD835\uDCAC",
                "qscr": "\uD835\uDCC6",
                "quaternions": "\u210D",
                "quatint": "\u2A16",
                "quest": "\u003F",
                "questeq": "\u225F",
                "QUOT": "\u0022",
                "quot": "\u0022",
                "rAarr": "\u21DB",
                "race": "\u223D\u0331",
                "Racute": "\u0154",
                "racute": "\u0155",
                "radic": "\u221A",
                "raemptyv": "\u29B3",
                "Rang": "\u27EB",
                "rang": "\u27E9",
                "rangd": "\u2992",
                "range": "\u29A5",
                "rangle": "\u27E9",
                "raquo": "\u00BB",
                "Rarr": "\u21A0",
                "rArr": "\u21D2",
                "rarr": "\u2192",
                "rarrap": "\u2975",
                "rarrb": "\u21E5",
                "rarrbfs": "\u2920",
                "rarrc": "\u2933",
                "rarrfs": "\u291E",
                "rarrhk": "\u21AA",
                "rarrlp": "\u21AC",
                "rarrpl": "\u2945",
                "rarrsim": "\u2974",
                "Rarrtl": "\u2916",
                "rarrtl": "\u21A3",
                "rarrw": "\u219D",
                "rAtail": "\u291C",
                "ratail": "\u291A",
                "ratio": "\u2236",
                "rationals": "\u211A",
                "RBarr": "\u2910",
                "rBarr": "\u290F",
                "rbarr": "\u290D",
                "rbbrk": "\u2773",
                "rbrace": "\u007D",
                "rbrack": "\u005D",
                "rbrke": "\u298C",
                "rbrksld": "\u298E",
                "rbrkslu": "\u2990",
                "Rcaron": "\u0158",
                "rcaron": "\u0159",
                "Rcedil": "\u0156",
                "rcedil": "\u0157",
                "rceil": "\u2309",
                "rcub": "\u007D",
                "Rcy": "\u0420",
                "rcy": "\u0440",
                "rdca": "\u2937",
                "rdldhar": "\u2969",
                "rdquo": "\u201D",
                "rdquor": "\u201D",
                "rdsh": "\u21B3",
                "Re": "\u211C",
                "real": "\u211C",
                "realine": "\u211B",
                "realpart": "\u211C",
                "reals": "\u211D",
                "rect": "\u25AD",
                "REG": "\u00AE",
                "reg": "\u00AE",
                "ReverseElement": "\u220B",
                "ReverseEquilibrium": "\u21CB",
                "ReverseUpEquilibrium": "\u296F",
                "rfisht": "\u297D",
                "rfloor": "\u230B",
                "Rfr": "\u211C",
                "rfr": "\uD835\uDD2F",
                "rHar": "\u2964",
                "rhard": "\u21C1",
                "rharu": "\u21C0",
                "rharul": "\u296C",
                "Rho": "\u03A1",
                "rho": "\u03C1",
                "rhov": "\u03F1",
                "RightAngleBracket": "\u27E9",
                "RightArrow": "\u2192",
                "Rightarrow": "\u21D2",
                "rightarrow": "\u2192",
                "RightArrowBar": "\u21E5",
                "RightArrowLeftArrow": "\u21C4",
                "rightarrowtail": "\u21A3",
                "RightCeiling": "\u2309",
                "RightDoubleBracket": "\u27E7",
                "RightDownTeeVector": "\u295D",
                "RightDownVector": "\u21C2",
                "RightDownVectorBar": "\u2955",
                "RightFloor": "\u230B",
                "rightharpoondown": "\u21C1",
                "rightharpoonup": "\u21C0",
                "rightleftarrows": "\u21C4",
                "rightleftharpoons": "\u21CC",
                "rightrightarrows": "\u21C9",
                "rightsquigarrow": "\u219D",
                "RightTee": "\u22A2",
                "RightTeeArrow": "\u21A6",
                "RightTeeVector": "\u295B",
                "rightthreetimes": "\u22CC",
                "RightTriangle": "\u22B3",
                "RightTriangleBar": "\u29D0",
                "RightTriangleEqual": "\u22B5",
                "RightUpDownVector": "\u294F",
                "RightUpTeeVector": "\u295C",
                "RightUpVector": "\u21BE",
                "RightUpVectorBar": "\u2954",
                "RightVector": "\u21C0",
                "RightVectorBar": "\u2953",
                "ring": "\u02DA",
                "risingdotseq": "\u2253",
                "rlarr": "\u21C4",
                "rlhar": "\u21CC",
                "rlm": "\u200F",
                "rmoust": "\u23B1",
                "rmoustache": "\u23B1",
                "rnmid": "\u2AEE",
                "roang": "\u27ED",
                "roarr": "\u21FE",
                "robrk": "\u27E7",
                "ropar": "\u2986",
                "Ropf": "\u211D",
                "ropf": "\uD835\uDD63",
                "roplus": "\u2A2E",
                "rotimes": "\u2A35",
                "RoundImplies": "\u2970",
                "rpar": "\u0029",
                "rpargt": "\u2994",
                "rppolint": "\u2A12",
                "rrarr": "\u21C9",
                "Rrightarrow": "\u21DB",
                "rsaquo": "\u203A",
                "Rscr": "\u211B",
                "rscr": "\uD835\uDCC7",
                "Rsh": "\u21B1",
                "rsh": "\u21B1",
                "rsqb": "\u005D",
                "rsquo": "\u2019",
                "rsquor": "\u2019",
                "rthree": "\u22CC",
                "rtimes": "\u22CA",
                "rtri": "\u25B9",
                "rtrie": "\u22B5",
                "rtrif": "\u25B8",
                "rtriltri": "\u29CE",
                "RuleDelayed": "\u29F4",
                "ruluhar": "\u2968",
                "rx": "\u211E",
                "Sacute": "\u015A",
                "sacute": "\u015B",
                "sbquo": "\u201A",
                "Sc": "\u2ABC",
                "sc": "\u227B",
                "scap": "\u2AB8",
                "Scaron": "\u0160",
                "scaron": "\u0161",
                "sccue": "\u227D",
                "scE": "\u2AB4",
                "sce": "\u2AB0",
                "Scedil": "\u015E",
                "scedil": "\u015F",
                "Scirc": "\u015C",
                "scirc": "\u015D",
                "scnap": "\u2ABA",
                "scnE": "\u2AB6",
                "scnsim": "\u22E9",
                "scpolint": "\u2A13",
                "scsim": "\u227F",
                "Scy": "\u0421",
                "scy": "\u0441",
                "sdot": "\u22C5",
                "sdotb": "\u22A1",
                "sdote": "\u2A66",
                "searhk": "\u2925",
                "seArr": "\u21D8",
                "searr": "\u2198",
                "searrow": "\u2198",
                "sect": "\u00A7",
                "semi": "\u003B",
                "seswar": "\u2929",
                "setminus": "\u2216",
                "setmn": "\u2216",
                "sext": "\u2736",
                "Sfr": "\uD835\uDD16",
                "sfr": "\uD835\uDD30",
                "sfrown": "\u2322",
                "sharp": "\u266F",
                "SHCHcy": "\u0429",
                "shchcy": "\u0449",
                "SHcy": "\u0428",
                "shcy": "\u0448",
                "ShortDownArrow": "\u2193",
                "ShortLeftArrow": "\u2190",
                "shortmid": "\u2223",
                "shortparallel": "\u2225",
                "ShortRightArrow": "\u2192",
                "ShortUpArrow": "\u2191",
                "shy": "\u00AD",
                "Sigma": "\u03A3",
                "sigma": "\u03C3",
                "sigmaf": "\u03C2",
                "sigmav": "\u03C2",
                "sim": "\u223C",
                "simdot": "\u2A6A",
                "sime": "\u2243",
                "simeq": "\u2243",
                "simg": "\u2A9E",
                "simgE": "\u2AA0",
                "siml": "\u2A9D",
                "simlE": "\u2A9F",
                "simne": "\u2246",
                "simplus": "\u2A24",
                "simrarr": "\u2972",
                "slarr": "\u2190",
                "SmallCircle": "\u2218",
                "smallsetminus": "\u2216",
                "smashp": "\u2A33",
                "smeparsl": "\u29E4",
                "smid": "\u2223",
                "smile": "\u2323",
                "smt": "\u2AAA",
                "smte": "\u2AAC",
                "smtes": "\u2AAC\uFE00",
                "SOFTcy": "\u042C",
                "softcy": "\u044C",
                "sol": "\u002F",
                "solb": "\u29C4",
                "solbar": "\u233F",
                "Sopf": "\uD835\uDD4A",
                "sopf": "\uD835\uDD64",
                "spades": "\u2660",
                "spadesuit": "\u2660",
                "spar": "\u2225",
                "sqcap": "\u2293",
                "sqcaps": "\u2293\uFE00",
                "sqcup": "\u2294",
                "sqcups": "\u2294\uFE00",
                "Sqrt": "\u221A",
                "sqsub": "\u228F",
                "sqsube": "\u2291",
                "sqsubset": "\u228F",
                "sqsubseteq": "\u2291",
                "sqsup": "\u2290",
                "sqsupe": "\u2292",
                "sqsupset": "\u2290",
                "sqsupseteq": "\u2292",
                "squ": "\u25A1",
                "Square": "\u25A1",
                "square": "\u25A1",
                "SquareIntersection": "\u2293",
                "SquareSubset": "\u228F",
                "SquareSubsetEqual": "\u2291",
                "SquareSuperset": "\u2290",
                "SquareSupersetEqual": "\u2292",
                "SquareUnion": "\u2294",
                "squarf": "\u25AA",
                "squf": "\u25AA",
                "srarr": "\u2192",
                "Sscr": "\uD835\uDCAE",
                "sscr": "\uD835\uDCC8",
                "ssetmn": "\u2216",
                "ssmile": "\u2323",
                "sstarf": "\u22C6",
                "Star": "\u22C6",
                "star": "\u2606",
                "starf": "\u2605",
                "straightepsilon": "\u03F5",
                "straightphi": "\u03D5",
                "strns": "\u00AF",
                "Sub": "\u22D0",
                "sub": "\u2282",
                "subdot": "\u2ABD",
                "subE": "\u2AC5",
                "sube": "\u2286",
                "subedot": "\u2AC3",
                "submult": "\u2AC1",
                "subnE": "\u2ACB",
                "subne": "\u228A",
                "subplus": "\u2ABF",
                "subrarr": "\u2979",
                "Subset": "\u22D0",
                "subset": "\u2282",
                "subseteq": "\u2286",
                "subseteqq": "\u2AC5",
                "SubsetEqual": "\u2286",
                "subsetneq": "\u228A",
                "subsetneqq": "\u2ACB",
                "subsim": "\u2AC7",
                "subsub": "\u2AD5",
                "subsup": "\u2AD3",
                "succ": "\u227B",
                "succapprox": "\u2AB8",
                "succcurlyeq": "\u227D",
                "Succeeds": "\u227B",
                "SucceedsEqual": "\u2AB0",
                "SucceedsSlantEqual": "\u227D",
                "SucceedsTilde": "\u227F",
                "succeq": "\u2AB0",
                "succnapprox": "\u2ABA",
                "succneqq": "\u2AB6",
                "succnsim": "\u22E9",
                "succsim": "\u227F",
                "SuchThat": "\u220B",
                "Sum": "\u2211",
                "sum": "\u2211",
                "sung": "\u266A",
                "Sup": "\u22D1",
                "sup": "\u2283",
                "sup1": "\u00B9",
                "sup2": "\u00B2",
                "sup3": "\u00B3",
                "supdot": "\u2ABE",
                "supdsub": "\u2AD8",
                "supE": "\u2AC6",
                "supe": "\u2287",
                "supedot": "\u2AC4",
                "Superset": "\u2283",
                "SupersetEqual": "\u2287",
                "suphsol": "\u27C9",
                "suphsub": "\u2AD7",
                "suplarr": "\u297B",
                "supmult": "\u2AC2",
                "supnE": "\u2ACC",
                "supne": "\u228B",
                "supplus": "\u2AC0",
                "Supset": "\u22D1",
                "supset": "\u2283",
                "supseteq": "\u2287",
                "supseteqq": "\u2AC6",
                "supsetneq": "\u228B",
                "supsetneqq": "\u2ACC",
                "supsim": "\u2AC8",
                "supsub": "\u2AD4",
                "supsup": "\u2AD6",
                "swarhk": "\u2926",
                "swArr": "\u21D9",
                "swarr": "\u2199",
                "swarrow": "\u2199",
                "swnwar": "\u292A",
                "szlig": "\u00DF",
                "Tab": "\u0009",
                "target": "\u2316",
                "Tau": "\u03A4",
                "tau": "\u03C4",
                "tbrk": "\u23B4",
                "Tcaron": "\u0164",
                "tcaron": "\u0165",
                "Tcedil": "\u0162",
                "tcedil": "\u0163",
                "Tcy": "\u0422",
                "tcy": "\u0442",
                "tdot": "\u20DB",
                "telrec": "\u2315",
                "Tfr": "\uD835\uDD17",
                "tfr": "\uD835\uDD31",
                "there4": "\u2234",
                "Therefore": "\u2234",
                "therefore": "\u2234",
                "Theta": "\u0398",
                "theta": "\u03B8",
                "thetasym": "\u03D1",
                "thetav": "\u03D1",
                "thickapprox": "\u2248",
                "thicksim": "\u223C",
                "ThickSpace": "\u205F\u200A",
                "thinsp": "\u2009",
                "ThinSpace": "\u2009",
                "thkap": "\u2248",
                "thksim": "\u223C",
                "THORN": "\u00DE",
                "thorn": "\u00FE",
                "Tilde": "\u223C",
                "tilde": "\u02DC",
                "TildeEqual": "\u2243",
                "TildeFullEqual": "\u2245",
                "TildeTilde": "\u2248",
                "times": "\u00D7",
                "timesb": "\u22A0",
                "timesbar": "\u2A31",
                "timesd": "\u2A30",
                "tint": "\u222D",
                "toea": "\u2928",
                "top": "\u22A4",
                "topbot": "\u2336",
                "topcir": "\u2AF1",
                "Topf": "\uD835\uDD4B",
                "topf": "\uD835\uDD65",
                "topfork": "\u2ADA",
                "tosa": "\u2929",
                "tprime": "\u2034",
                "TRADE": "\u2122",
                "trade": "\u2122",
                "triangle": "\u25B5",
                "triangledown": "\u25BF",
                "triangleleft": "\u25C3",
                "trianglelefteq": "\u22B4",
                "triangleq": "\u225C",
                "triangleright": "\u25B9",
                "trianglerighteq": "\u22B5",
                "tridot": "\u25EC",
                "trie": "\u225C",
                "triminus": "\u2A3A",
                "TripleDot": "\u20DB",
                "triplus": "\u2A39",
                "trisb": "\u29CD",
                "tritime": "\u2A3B",
                "trpezium": "\u23E2",
                "Tscr": "\uD835\uDCAF",
                "tscr": "\uD835\uDCC9",
                "TScy": "\u0426",
                "tscy": "\u0446",
                "TSHcy": "\u040B",
                "tshcy": "\u045B",
                "Tstrok": "\u0166",
                "tstrok": "\u0167",
                "twixt": "\u226C",
                "twoheadleftarrow": "\u219E",
                "twoheadrightarrow": "\u21A0",
                "Uacute": "\u00DA",
                "uacute": "\u00FA",
                "Uarr": "\u219F",
                "uArr": "\u21D1",
                "uarr": "\u2191",
                "Uarrocir": "\u2949",
                "Ubrcy": "\u040E",
                "ubrcy": "\u045E",
                "Ubreve": "\u016C",
                "ubreve": "\u016D",
                "Ucirc": "\u00DB",
                "ucirc": "\u00FB",
                "Ucy": "\u0423",
                "ucy": "\u0443",
                "udarr": "\u21C5",
                "Udblac": "\u0170",
                "udblac": "\u0171",
                "udhar": "\u296E",
                "ufisht": "\u297E",
                "Ufr": "\uD835\uDD18",
                "ufr": "\uD835\uDD32",
                "Ugrave": "\u00D9",
                "ugrave": "\u00F9",
                "uHar": "\u2963",
                "uharl": "\u21BF",
                "uharr": "\u21BE",
                "uhblk": "\u2580",
                "ulcorn": "\u231C",
                "ulcorner": "\u231C",
                "ulcrop": "\u230F",
                "ultri": "\u25F8",
                "Umacr": "\u016A",
                "umacr": "\u016B",
                "uml": "\u00A8",
                "UnderBar": "\u005F",
                "UnderBrace": "\u23DF",
                "UnderBracket": "\u23B5",
                "UnderParenthesis": "\u23DD",
                "Union": "\u22C3",
                "UnionPlus": "\u228E",
                "Uogon": "\u0172",
                "uogon": "\u0173",
                "Uopf": "\uD835\uDD4C",
                "uopf": "\uD835\uDD66",
                "UpArrow": "\u2191",
                "Uparrow": "\u21D1",
                "uparrow": "\u2191",
                "UpArrowBar": "\u2912",
                "UpArrowDownArrow": "\u21C5",
                "UpDownArrow": "\u2195",
                "Updownarrow": "\u21D5",
                "updownarrow": "\u2195",
                "UpEquilibrium": "\u296E",
                "upharpoonleft": "\u21BF",
                "upharpoonright": "\u21BE",
                "uplus": "\u228E",
                "UpperLeftArrow": "\u2196",
                "UpperRightArrow": "\u2197",
                "Upsi": "\u03D2",
                "upsi": "\u03C5",
                "upsih": "\u03D2",
                "Upsilon": "\u03A5",
                "upsilon": "\u03C5",
                "UpTee": "\u22A5",
                "UpTeeArrow": "\u21A5",
                "upuparrows": "\u21C8",
                "urcorn": "\u231D",
                "urcorner": "\u231D",
                "urcrop": "\u230E",
                "Uring": "\u016E",
                "uring": "\u016F",
                "urtri": "\u25F9",
                "Uscr": "\uD835\uDCB0",
                "uscr": "\uD835\uDCCA",
                "utdot": "\u22F0",
                "Utilde": "\u0168",
                "utilde": "\u0169",
                "utri": "\u25B5",
                "utrif": "\u25B4",
                "uuarr": "\u21C8",
                "Uuml": "\u00DC",
                "uuml": "\u00FC",
                "uwangle": "\u29A7",
                "vangrt": "\u299C",
                "varepsilon": "\u03F5",
                "varkappa": "\u03F0",
                "varnothing": "\u2205",
                "varphi": "\u03D5",
                "varpi": "\u03D6",
                "varpropto": "\u221D",
                "vArr": "\u21D5",
                "varr": "\u2195",
                "varrho": "\u03F1",
                "varsigma": "\u03C2",
                "varsubsetneq": "\u228A\uFE00",
                "varsubsetneqq": "\u2ACB\uFE00",
                "varsupsetneq": "\u228B\uFE00",
                "varsupsetneqq": "\u2ACC\uFE00",
                "vartheta": "\u03D1",
                "vartriangleleft": "\u22B2",
                "vartriangleright": "\u22B3",
                "Vbar": "\u2AEB",
                "vBar": "\u2AE8",
                "vBarv": "\u2AE9",
                "Vcy": "\u0412",
                "vcy": "\u0432",
                "VDash": "\u22AB",
                "Vdash": "\u22A9",
                "vDash": "\u22A8",
                "vdash": "\u22A2",
                "Vdashl": "\u2AE6",
                "Vee": "\u22C1",
                "vee": "\u2228",
                "veebar": "\u22BB",
                "veeeq": "\u225A",
                "vellip": "\u22EE",
                "Verbar": "\u2016",
                "verbar": "\u007C",
                "Vert": "\u2016",
                "vert": "\u007C",
                "VerticalBar": "\u2223",
                "VerticalLine": "\u007C",
                "VerticalSeparator": "\u2758",
                "VerticalTilde": "\u2240",
                "VeryThinSpace": "\u200A",
                "Vfr": "\uD835\uDD19",
                "vfr": "\uD835\uDD33",
                "vltri": "\u22B2",
                "vnsub": "\u2282\u20D2",
                "vnsup": "\u2283\u20D2",
                "Vopf": "\uD835\uDD4D",
                "vopf": "\uD835\uDD67",
                "vprop": "\u221D",
                "vrtri": "\u22B3",
                "Vscr": "\uD835\uDCB1",
                "vscr": "\uD835\uDCCB",
                "vsubnE": "\u2ACB\uFE00",
                "vsubne": "\u228A\uFE00",
                "vsupnE": "\u2ACC\uFE00",
                "vsupne": "\u228B\uFE00",
                "Vvdash": "\u22AA",
                "vzigzag": "\u299A",
                "Wcirc": "\u0174",
                "wcirc": "\u0175",
                "wedbar": "\u2A5F",
                "Wedge": "\u22C0",
                "wedge": "\u2227",
                "wedgeq": "\u2259",
                "weierp": "\u2118",
                "Wfr": "\uD835\uDD1A",
                "wfr": "\uD835\uDD34",
                "Wopf": "\uD835\uDD4E",
                "wopf": "\uD835\uDD68",
                "wp": "\u2118",
                "wr": "\u2240",
                "wreath": "\u2240",
                "Wscr": "\uD835\uDCB2",
                "wscr": "\uD835\uDCCC",
                "xcap": "\u22C2",
                "xcirc": "\u25EF",
                "xcup": "\u22C3",
                "xdtri": "\u25BD",
                "Xfr": "\uD835\uDD1B",
                "xfr": "\uD835\uDD35",
                "xhArr": "\u27FA",
                "xharr": "\u27F7",
                "Xi": "\u039E",
                "xi": "\u03BE",
                "xlArr": "\u27F8",
                "xlarr": "\u27F5",
                "xmap": "\u27FC",
                "xnis": "\u22FB",
                "xodot": "\u2A00",
                "Xopf": "\uD835\uDD4F",
                "xopf": "\uD835\uDD69",
                "xoplus": "\u2A01",
                "xotime": "\u2A02",
                "xrArr": "\u27F9",
                "xrarr": "\u27F6",
                "Xscr": "\uD835\uDCB3",
                "xscr": "\uD835\uDCCD",
                "xsqcup": "\u2A06",
                "xuplus": "\u2A04",
                "xutri": "\u25B3",
                "xvee": "\u22C1",
                "xwedge": "\u22C0",
                "Yacute": "\u00DD",
                "yacute": "\u00FD",
                "YAcy": "\u042F",
                "yacy": "\u044F",
                "Ycirc": "\u0176",
                "ycirc": "\u0177",
                "Ycy": "\u042B",
                "ycy": "\u044B",
                "yen": "\u00A5",
                "Yfr": "\uD835\uDD1C",
                "yfr": "\uD835\uDD36",
                "YIcy": "\u0407",
                "yicy": "\u0457",
                "Yopf": "\uD835\uDD50",
                "yopf": "\uD835\uDD6A",
                "Yscr": "\uD835\uDCB4",
                "yscr": "\uD835\uDCCE",
                "YUcy": "\u042E",
                "yucy": "\u044E",
                "Yuml": "\u0178",
                "yuml": "\u00FF",
                "Zacute": "\u0179",
                "zacute": "\u017A",
                "Zcaron": "\u017D",
                "zcaron": "\u017E",
                "Zcy": "\u0417",
                "zcy": "\u0437",
                "Zdot": "\u017B",
                "zdot": "\u017C",
                "zeetrf": "\u2128",
                "ZeroWidthSpace": "\u200B",
                "Zeta": "\u0396",
                "zeta": "\u03B6",
                "Zfr": "\u2128",
                "zfr": "\uD835\uDD37",
                "ZHcy": "\u0416",
                "zhcy": "\u0436",
                "zigrarr": "\u21DD",
                "Zopf": "\u2124",
                "zopf": "\uD835\uDD6B",
                "Zscr": "\uD835\uDCB5",
                "zscr": "\uD835\uDCCF",
                "zwj": "\u200D",
                "zwnj": "\u200C"
            };

        }, {}],
        2: [function (require, module, exports) {
// List of valid html blocks names, accorting to commonmark spec
// http://jgm.github.io/CommonMark/spec.html#html-blocks

            'use strict';

            var html_blocks = {};

            [
                'article',
                'aside',
                'button',
                'blockquote',
                'body',
                'canvas',
                'caption',
                'col',
                'colgroup',
                'dd',
                'div',
                'dl',
                'dt',
                'embed',
                'fieldset',
                'figcaption',
                'figure',
                'footer',
                'form',
                'h1',
                'h2',
                'h3',
                'h4',
                'h5',
                'h6',
                'header',
                'hgroup',
                'hr',
                'iframe',
                'li',
                'map',
                'object',
                'ol',
                'output',
                'p',
                'pre',
                'progress',
                'script',
                'section',
                'style',
                'table',
                'tbody',
                'td',
                'textarea',
                'tfoot',
                'th',
                'tr',
                'thead',
                'ul',
                'video'
            ].forEach(function (name) {
                html_blocks[name] = true;
            });


            module.exports = html_blocks;

        }, {}],
        3: [function (require, module, exports) {
// Regexps to match html elements

            'use strict';


            function replace(regex, options) {
                regex = regex.source;
                options = options || '';

                return function self(name, val) {
                    if (!name) {
                        return new RegExp(regex, options);
                    }
                    val = val.source;
                    regex = regex.replace(name, val);
                    return self;
                };
            }


            var attr_name = /[a-zA-Z_:][a-zA-Z0-9:._-]*/;

            var unquoted = /[^"'=<>`\x00-\x20]+/;
            var single_quoted = /'[^']*'/;
            var double_quoted = /"[^"]*"/;

            /*eslint no-spaced-func:0*/
            var attr_value = replace(/(?:unquoted|single_quoted|double_quoted)/)
            ('unquoted', unquoted)
            ('single_quoted', single_quoted)
            ('double_quoted', double_quoted)
            ();

            var attribute = replace(/(?:\s+attr_name(?:\s*=\s*attr_value)?)/)
            ('attr_name', attr_name)
            ('attr_value', attr_value)
            ();

            var open_tag = replace(/<[A-Za-z][A-Za-z0-9\-]*attribute*\s*\/?>/)
            ('attribute', attribute)
            ();

            var close_tag = /<\/[A-Za-z][A-Za-z0-9\-]*\s*>/;
// That's less strict than http://www.w3.org/TR/html5/syntax.html#comments
// but we do the rest of check in "inline" rule.
            var comment = /<!--[\s\S]*?-->/;
            var processing = /<[?].*?[?]>/;
            var declaration = /<![A-Z]+\s+[^>]*>/;
            var cdata = /<!\[CDATA\[[\s\S]*?\]\]>/;

            var HTML_TAG_RE = replace(/^(?:open_tag|close_tag|comment|processing|declaration|cdata)/)
            ('open_tag', open_tag)
            ('close_tag', close_tag)
            ('comment', comment)
            ('processing', processing)
            ('declaration', declaration)
            ('cdata', cdata)
            ();


            module.exports.HTML_TAG_RE = HTML_TAG_RE;

        }, {}],
        4: [function (require, module, exports) {
// List of valid url schemas, accorting to commonmark spec
// http://jgm.github.io/CommonMark/spec.html#autolinks

            'use strict';


            module.exports = [
                'coap',
                'doi',
                'javascript',
                'aaa',
                'aaas',
                'about',
                'acap',
                'cap',
                'cid',
                'crid',
                'data',
                'dav',
                'dict',
                'dns',
                'file',
                'ftp',
                'geo',
                'go',
                'gopher',
                'h323',
                'http',
                'https',
                'iax',
                'icap',
                'im',
                'imap',
                'info',
                'ipp',
                'iris',
                'iris.beep',
                'iris.xpc',
                'iris.xpcs',
                'iris.lwz',
                'ldap',
                'mailto',
                'mid',
                'msrp',
                'msrps',
                'mtqp',
                'mupdate',
                'news',
                'nfs',
                'ni',
                'nih',
                'nntp',
                'opaquelocktoken',
                'pop',
                'pres',
                'rtsp',
                'service',
                'session',
                'shttp',
                'sieve',
                'sip',
                'sips',
                'sms',
                'snmp',
                'soap.beep',
                'soap.beeps',
                'tag',
                'tel',
                'telnet',
                'tftp',
                'thismessage',
                'tn3270',
                'tip',
                'tv',
                'urn',
                'vemmi',
                'ws',
                'wss',
                'xcon',
                'xcon-userid',
                'xmlrpc.beep',
                'xmlrpc.beeps',
                'xmpp',
                'z39.50r',
                'z39.50s',
                'adiumxtra',
                'afp',
                'afs',
                'aim',
                'apt',
                'attachment',
                'aw',
                'beshare',
                'bitcoin',
                'bolo',
                'callto',
                'chrome',
                'chrome-extension',
                'com-eventbrite-attendee',
                'content',
                'cvs',
                'dlna-playsingle',
                'dlna-playcontainer',
                'dtn',
                'dvb',
                'ed2k',
                'facetime',
                'feed',
                'finger',
                'fish',
                'gg',
                'git',
                'gizmoproject',
                'gtalk',
                'hcp',
                'icon',
                'ipn',
                'irc',
                'irc6',
                'ircs',
                'itms',
                'jar',
                'jms',
                'keyparc',
                'lastfm',
                'ldaps',
                'magnet',
                'maps',
                'market',
                'message',
                'mms',
                'ms-help',
                'msnim',
                'mumble',
                'mvn',
                'notes',
                'oid',
                'palm',
                'paparazzi',
                'platform',
                'proxy',
                'psyc',
                'query',
                'res',
                'resource',
                'rmi',
                'rsync',
                'rtmp',
                'secondlife',
                'sftp',
                'sgn',
                'skype',
                'smb',
                'soldat',
                'spotify',
                'ssh',
                'steam',
                'svn',
                'teamspeak',
                'things',
                'udp',
                'unreal',
                'ut2004',
                'ventrilo',
                'view-source',
                'webcal',
                'wtai',
                'wyciwyg',
                'xfire',
                'xri',
                'ymsgr'
            ];

        }, {}],
        5: [function (require, module, exports) {
// Utilities
//
            'use strict';


            function _class(obj) {
                return Object.prototype.toString.call(obj);
            }

            function isString(obj) {
                return _class(obj) === '[object String]';
            }

            var _hasOwnProperty = Object.prototype.hasOwnProperty;

            function has(object, key) {
                return _hasOwnProperty.call(object, key);
            }

// Merge objects
//
            function assign(obj /*from1, from2, from3, ...*/) {
                var sources = Array.prototype.slice.call(arguments, 1);

                sources.forEach(function (source) {
                    if (!source) {
                        return;
                    }

                    if (typeof source !== 'object') {
                        throw new TypeError(source + 'must be object');
                    }

                    Object.keys(source).forEach(function (key) {
                        obj[key] = source[key];
                    });
                });

                return obj;
            }

// Remove element from array and put another array at those position.
// Useful for some operations with tokens
            function arrayReplaceAt(src, pos, newElements) {
                return [].concat(src.slice(0, pos), newElements, src.slice(pos + 1));
            }

////////////////////////////////////////////////////////////////////////////////

            var UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])/g;

            function unescapeMd(str) {
                if (str.indexOf('\\') < 0) {
                    return str;
                }
                return str.replace(UNESCAPE_MD_RE, '$1');
            }

////////////////////////////////////////////////////////////////////////////////

            function isValidEntityCode(c) {
                /*eslint no-bitwise:0*/
                // broken sequence
                if (c >= 0xD800 && c <= 0xDFFF) {
                    return false;
                }
                // never used
                if (c >= 0xFDD0 && c <= 0xFDEF) {
                    return false;
                }
                if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE) {
                    return false;
                }
                // control codes
                if (c >= 0x00 && c <= 0x08) {
                    return false;
                }
                if (c === 0x0B) {
                    return false;
                }
                if (c >= 0x0E && c <= 0x1F) {
                    return false;
                }
                if (c >= 0x7F && c <= 0x9F) {
                    return false;
                }
                // out of range
                if (c > 0x10FFFF) {
                    return false;
                }
                return true;
            }

            function fromCodePoint(c) {
                /*eslint no-bitwise:0*/
                if (c > 0xffff) {
                    c -= 0x10000;
                    var surrogate1 = 0xd800 + (c >> 10),
                        surrogate2 = 0xdc00 + (c & 0x3ff);

                    return String.fromCharCode(surrogate1, surrogate2);
                }
                return String.fromCharCode(c);
            }

            var NAMED_ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;
            var DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i;
            var entities = require('./entities');

            function replaceEntityPattern(match, name) {
                var code = 0;

                if (has(entities, name)) {
                    return entities[name];
                } else if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) {
                    code = name[1].toLowerCase() === 'x' ?
                        parseInt(name.slice(2), 16)
                        :
                        parseInt(name.slice(1), 10);
                    if (isValidEntityCode(code)) {
                        return fromCodePoint(code);
                    }
                }
                return match;
            }

            function replaceEntities(str) {
                if (str.indexOf('&') < 0) {
                    return str;
                }

                return str.replace(NAMED_ENTITY_RE, replaceEntityPattern);
            }

////////////////////////////////////////////////////////////////////////////////

            var HTML_ESCAPE_TEST_RE = /[&<>"]/;
            var HTML_ESCAPE_REPLACE_RE = /[&<>"]/g;
            var HTML_REPLACEMENTS = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;'
            };

            function replaceUnsafeChar(ch) {
                return HTML_REPLACEMENTS[ch];
            }

            function escapeHtml(str) {
                if (HTML_ESCAPE_TEST_RE.test(str)) {
                    return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar);
                }
                return str;
            }

////////////////////////////////////////////////////////////////////////////////

            var SURRORATE_TEST_RE = /[\uD800-\uDFFF]/;
            var SURRORATE_SEARCH_RE = /[\uD800-\uDFFF]/g;

            function replaceBadSurrogate(ch, pos, orig) {
                var code = ch.charCodeAt(0);

                if (code >= 0xD800 && code <= 0xDBFF) {
                    // high surrogate
                    if (pos >= orig.length - 1) {
                        return '\uFFFD';
                    }
                    code = orig.charCodeAt(pos + 1);
                    if (code < 0xDC00 || code > 0xDFFF) {
                        return '\uFFFD';
                    }

                    return ch;
                }

                // low surrogate
                if (pos === 0) {
                    return '\uFFFD';
                }
                code = orig.charCodeAt(pos - 1);
                if (code < 0xD900 || code > 0xDBFF) {
                    return '\uFFFD';
                }
                return ch;
            }

            function fixBrokenSurrogates(str) {
                if (!SURRORATE_TEST_RE.test(str)) {
                    return str;
                }

                return str.replace(SURRORATE_SEARCH_RE, replaceBadSurrogate);
            }

////////////////////////////////////////////////////////////////////////////////


// Incoming link can be partially encoded. Convert possible combinations to
// unified form.
//
// TODO: Rewrite it. Should use:
//
// - encodeURIComponent for query
// - encodeURI for path
// - (?) punicode for domain mame (but encodeURI seems to work in real world)
//
            function normalizeLink(url) {
                var normalized = replaceEntities(url);

                // We don't care much about result of mailformed URIs,
                // but shoud not throw exception.
                try {
                    normalized = decodeURI(normalized);
                } catch (__) {
                }

                // Encoder throws exception on broken surrogate pairs.
                // Fix those first.
                return encodeURI(fixBrokenSurrogates(normalized));
            }

////////////////////////////////////////////////////////////////////////////////

            var REGEXP_ESCAPE_RE = /[.?*+^$[\]\\(){}|-]/g;

            function escapeRE(str) {
                return str.replace(REGEXP_ESCAPE_RE, '\\$&');
            }

////////////////////////////////////////////////////////////////////////////////

// Zs (unicode class) || 09, 0A, 0D, 0C
            function isWhiteSpace(code) {
                if (code >= 0x2000 && code <= 0x200A) {
                    return true;
                }
                switch (code) {
                    case 0x09:
                    case 0x0A:
                    case 0x0D:
                    case 0x0C:
                    case 0x20:
                    case 0xA0:
                    case 0x1680:
                    case 0x202F:
                    case 0x205F:
                    case 0x3000:
                        return true;
                }
                return false;
            }

////////////////////////////////////////////////////////////////////////////////

            /*eslint-disable max-len*/
            var BMP_PUNCT_RE = /[\x21-\x23\x25-\x2A\x2C-\x2F\x3A\x3B\x3F\x40\x5B-\x5D\x5F\x7B\x7D\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]/;

// Currently without astral characters support.
            function isPunctChar(char) {
                return BMP_PUNCT_RE.test(char);
            }


// Markdown ASCII punctuation characters.
//
// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
// http://spec.commonmark.org/0.15/#ascii-punctuation-character
//
// Don't confuse with unicode punctuation !!! It lacks some chars in ascii range.
//
            function isMdAsciiPunct(ch) {
                switch (ch) {
                    case 0x21/* ! */
                    :
                    case 0x22/* " */
                    :
                    case 0x23/* # */
                    :
                    case 0x24/* $ */
                    :
                    case 0x25/* % */
                    :
                    case 0x26/* & */
                    :
                    case 0x27/* ' */
                    :
                    case 0x28/* ( */
                    :
                    case 0x29/* ) */
                    :
                    case 0x2A/* * */
                    :
                    case 0x2B/* + */
                    :
                    case 0x2C/* , */
                    :
                    case 0x2D/* - */
                    :
                    case 0x2E/* . */
                    :
                    case 0x2F/* / */
                    :
                    case 0x3A/* : */
                    :
                    case 0x3B/* ; */
                    :
                    case 0x3C/* < */
                    :
                    case 0x3D/* = */
                    :
                    case 0x3E/* > */
                    :
                    case 0x3F/* ? */
                    :
                    case 0x40/* @ */
                    :
                    case 0x5B/* [ */
                    :
                    case 0x5C/* \ */
                    :
                    case 0x5D/* ] */
                    :
                    case 0x5E/* ^ */
                    :
                    case 0x5F/* _ */
                    :
                    case 0x60/* ` */
                    :
                    case 0x7B/* { */
                    :
                    case 0x7C/* | */
                    :
                    case 0x7D/* } */
                    :
                    case 0x7E/* ~ */
                    :
                        return true;
                    default:
                        return false;
                }
            }

////////////////////////////////////////////////////////////////////////////////

            exports.assign = assign;
            exports.isString = isString;
            exports.has = has;
            exports.unescapeMd = unescapeMd;
            exports.isValidEntityCode = isValidEntityCode;
            exports.fromCodePoint = fromCodePoint;
            exports.replaceEntities = replaceEntities;
            exports.escapeHtml = escapeHtml;
            exports.arrayReplaceAt = arrayReplaceAt;
            exports.normalizeLink = normalizeLink;
            exports.isWhiteSpace = isWhiteSpace;
            exports.isMdAsciiPunct = isMdAsciiPunct;
            exports.isPunctChar = isPunctChar;
            exports.escapeRE = escapeRE;

        }, {"./entities": 1}],
        6: [function (require, module, exports) {
// Just a shortcut for bulk export
            'use strict';


            exports.parseLinkLabel = require('./parse_link_label');
            exports.parseLinkDestination = require('./parse_link_destination');
            exports.parseLinkTitle = require('./parse_link_title');

        }, {"./parse_link_destination": 8, "./parse_link_label": 9, "./parse_link_title": 10}],
        7: [function (require, module, exports) {
            'use strict';


// Hepler to [reference labels]. No better place for this code :)
// It's only for refs/links and should not be exported anywhere.
            module.exports = function normalizeReference(str) {
                // use .toUpperCase() instead of .toLowerCase()
                // here to avoid a conflict with Object.prototype
                // members (most notably, `__proto__`)
                return str.trim().replace(/\s+/g, ' ').toUpperCase();
            };

        }, {}],
        8: [function (require, module, exports) {
// Parse link destination
//
            'use strict';


            var normalizeLink = require('../common/utils').normalizeLink;
            var unescapeMd = require('../common/utils').unescapeMd;


            module.exports = function parseLinkDestination(str, pos, max) {
                var code, level,
                    lines = 0,
                    start = pos,
                    result = {
                        ok: false,
                        pos: 0,
                        lines: 0,
                        str: ''
                    };

                if (str.charCodeAt(pos) === 0x3C /* < */) {
                    pos++;
                    while (pos < max) {
                        code = str.charCodeAt(pos);
                        if (code === 0x0A /* \n */) {
                            return result;
                        }
                        if (code === 0x3E /* > */) {
                            result.pos = pos + 1;
                            result.str = normalizeLink(unescapeMd(str.slice(start + 1, pos)));
                            result.ok = true;
                            return result;
                        }
                        if (code === 0x5C /* \ */ && pos + 1 < max) {
                            pos += 2;
                            continue;
                        }

                        pos++;
                    }

                    // no closing '>'
                    return result;
                }

                // this should be ... } else { ... branch

                level = 0;
                while (pos < max) {
                    code = str.charCodeAt(pos);

                    if (code === 0x20) {
                        break;
                    }

                    // ascii control characters
                    if (code < 0x20 || code === 0x7F) {
                        break;
                    }

                    if (code === 0x5C /* \ */ && pos + 1 < max) {
                        pos += 2;
                        continue;
                    }

                    if (code === 0x28 /* ( */) {
                        level++;
                        if (level > 1) {
                            break;
                        }
                    }

                    if (code === 0x29 /* ) */) {
                        level--;
                        if (level < 0) {
                            break;
                        }
                    }

                    pos++;
                }

                if (start === pos) {
                    return result;
                }

                result.str = normalizeLink(unescapeMd(str.slice(start, pos)));
                result.lines = lines;
                result.pos = pos;
                result.ok = true;
                return result;
            };

        }, {"../common/utils": 5}],
        9: [function (require, module, exports) {
// Parse link label
//
// this function assumes that first character ("[") already matches;
// returns the end of the label
//
            'use strict';

            module.exports = function parseLinkLabel(state, start, disableNested) {
                var level, found, marker, prevPos,
                    labelEnd = -1,
                    max = state.posMax,
                    oldPos = state.pos;

                if (state.labelUnmatchedScopes) {
                    state.labelUnmatchedScopes--;
                    return -1;
                }

                state.pos = start + 1;
                level = 1;

                while (state.pos < max) {
                    marker = state.src.charCodeAt(state.pos);
                    if (marker === 0x5D /* ] */) {
                        level--;
                        if (level === 0) {
                            found = true;
                            break;
                        }
                    }

                    prevPos = state.pos;
                    state.md.inline.skipToken(state);
                    if (marker === 0x5B /* [ */) {
                        if (prevPos === state.pos - 1) {
                            // increase level if we find text `[`, which is not a part of any token
                            level++;
                        } else if (disableNested) {
                            state.pos = oldPos;
                            return -1;
                        }
                    }
                }

                if (found) {
                    labelEnd = state.pos;
                    state.labelUnmatchedScopes = 0;
                } else {
                    state.labelUnmatchedScopes = level - 1;
                }

                // restore old state
                state.pos = oldPos;

                return labelEnd;
            };

        }, {}],
        10: [function (require, module, exports) {
// Parse link title
//
            'use strict';


            var unescapeMd = require('../common/utils').unescapeMd;


            module.exports = function parseLinkTitle(str, pos, max) {
                var code,
                    marker,
                    lines = 0,
                    start = pos,
                    result = {
                        ok: false,
                        pos: 0,
                        lines: 0,
                        str: ''
                    };

                if (pos >= max) {
                    return result;
                }

                marker = str.charCodeAt(pos);

                if (marker !== 0x22 /* " */ && marker !== 0x27 /* ' */ && marker !== 0x28 /* ( */) {
                    return result;
                }

                pos++;

                // if opening marker is "(", switch it to closing marker ")"
                if (marker === 0x28) {
                    marker = 0x29;
                }

                while (pos < max) {
                    code = str.charCodeAt(pos);
                    if (code === marker) {
                        result.pos = pos + 1;
                        result.lines = lines;
                        result.str = unescapeMd(str.slice(start + 1, pos));
                        result.ok = true;
                        return result;
                    } else if (code === 0x0A) {
                        lines++;
                    } else if (code === 0x5C /* \ */ && pos + 1 < max) {
                        pos++;
                        if (str.charCodeAt(pos) === 0x0A) {
                            lines++;
                        }
                    }

                    pos++;
                }

                return result;
            };

        }, {"../common/utils": 5}],
        11: [function (require, module, exports) {
// Main perser class

            'use strict';


            var utils = require('./common/utils');
            var helpers = require('./helpers');
            var Renderer = require('./renderer');
            var ParserCore = require('./parser_core');
            var ParserBlock = require('./parser_block');
            var ParserInline = require('./parser_inline');

            var config = {
                'default': require('./presets/default'),
                zero: require('./presets/zero'),
                commonmark: require('./presets/commonmark')
            };


            /**
             * class MarkdownIt
             *
             * Main parser/renderer class.
             *
             * ##### Usage
             *
             * ```javascript
             * // node.js, "classic" way:
             * var MarkdownIt = require('markdown-it'),
             *     md = new MarkdownIt();
             * var result = md.render('# markdown-it rulezz!');
             *
             * // node.js, the same, but with sugar:
             * var md = require('markdown-it')();
             * var result = md.render('# markdown-it rulezz!');
             *
             * // browser without AMD, added to "window" on script load
             * // Note, there are no dash.
             * var md = window.markdownit();
             * var result = md.render('# markdown-it rulezz!');
             * ```
             *
             * Single line rendering, without paragraph wrap:
             *
             * ```javascript
             * var md = require('markdown-it')();
             * var result = md.renderInline('__markdown-it__ rulezz!');
             * ```
             **/

            /**
             * new MarkdownIt([presetName, options])
             * - presetName (String): optional, `commonmark` / `zero`
             * - options (Object)
             *
             * Creates parser instanse with given config. Can be called without `new`.
             *
             * ##### presetName
             *
             * MarkdownIt provides named presets as a convenience to quickly
             * enable/disable active syntax rules and options for common use cases.
             *
             * - ["commonmark"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) -
             *   configures parser to strict [CommonMark](http://commonmark.org/) mode.
             * - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) -
             *   similar to GFM, used when no preset name given. Enables all available rules,
             *   but still without html, typographer & autolinker.
             * - ["zero"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) -
             *   all rules disabled. Useful to quickly setup your config via `.enable()`.
             *   For example, when you need only `bold` and `italic` markup and nothing else.
             *
             * ##### options:
             *
             * - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful!
             *   That's not safe! You may need external sanitizer to protect output from XSS.
             *   It's better to extend features via plugins, instead of enabling HTML.
             * - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags
             *   (`<br />`). This is needed only for full CommonMark compatibility. In real
             *   world you will need HTML output.
             * - __breaks__ - `false`. Set `true` to convert `\n` in paragraphs into `<br>`.
             * - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks.
             *   Can be useful for external highlighters.
             * - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links.
             * - __typographer__  - `false`. Set `true` to enable [some language-neutral
             *   replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +
             *   quotes beautification (smartquotes).
             * - __quotes__ - `“”‘’`, string. Double + single quotes replacement pairs, when
             *   typographer enabled and smartquotes on. Set doubles to '«»' for Russian,
             *   '„“' for German.
             * - __highlight__ - `null`. Highlighter function for fenced code blocks.
             *   Highlighter `function (str, lang)` should return escaped HTML. It can also
             *   return empty string if the source was not changed and should be escaped externaly.
             *
             * ##### Example
             *
             * ```javascript
             * // commonmark mode
             * var md = require('markdown-it')('commonmark');
             *
             * // default mode
             * var md = require('markdown-it')();
             *
             * // enable everything
             * var md = require('markdown-it')({
 *   html: true,
 *   linkify: true,
 *   typographer: true
 * });
             * ```
             *
             * ##### Syntax highlighting
             *
             * ```js
             * var hljs = require('highlight.js') // https://highlightjs.org/
             *
             * var md = require('markdown-it')({
 *   highlight: function (str, lang) {
 *     if (lang && hljs.getLanguage(lang)) {
 *       try {
 *         return hljs.highlight(lang, str).value;
 *       } catch (__) {}
 *     }
 *
 *     try {
 *       return hljs.highlightAuto(str).value;
 *     } catch (__) {}
 *
 *     return ''; // use external default escaping
 *   }
 * });
             * ```
             **/
            function MarkdownIt(presetName, options) {
                if (!(this instanceof MarkdownIt)) {
                    return new MarkdownIt(presetName, options);
                }

                if (!options) {
                    if (!utils.isString(presetName)) {
                        options = presetName || {};
                        presetName = 'default';
                    }
                }

                /**
                 * MarkdownIt#inline -> ParserInline
                 *
                 * Instance of [[ParserInline]]. You may need it to add new rules when
                 * writing plugins. For simple rules control use [[MarkdownIt.disable]] and
                 * [[MarkdownIt.enable]].
                 **/
                this.inline = new ParserInline();

                /**
                 * MarkdownIt#block -> ParserBlock
                 *
                 * Instance of [[ParserBlock]]. You may need it to add new rules when
                 * writing plugins. For simple rules control use [[MarkdownIt.disable]] and
                 * [[MarkdownIt.enable]].
                 **/
                this.block = new ParserBlock();

                /**
                 * MarkdownIt#core -> Core
                 *
                 * Instance of [[Core]] chain executor. You may need it to add new rules when
                 * writing plugins. For simple rules control use [[MarkdownIt.disable]] and
                 * [[MarkdownIt.enable]].
                 **/
                this.core = new ParserCore();

                /**
                 * MarkdownIt#renderer -> Renderer
                 *
                 * Instance of [[Renderer]]. Use it to modify output look. Or to add rendering
                 * rules for new token types, generated by plugins.
                 *
                 * ##### Example
                 *
                 * ```javascript
                 * var md = require('markdown-it')();
                 *
                 * function myToken(tokens, idx, options, env, self) {
   *   //...
   *   return result;
   * };
                 *
                 * md.renderer.rules['my_token'] = myToken
                 * ```
                 *
                 * See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).
                 **/
                this.renderer = new Renderer();

                // Expose utils & helpers for easy acces from plugins

                /**
                 * MarkdownIt#utils -> utils
                 *
                 * Assorted utility functions, useful to write plugins. See details
                 * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js).
                 **/
                this.utils = utils;

                /**
                 * MarkdownIt#helpers -> helpers
                 *
                 * Link components parser functions, useful to write plugins. See details
                 * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).
                 **/
                this.helpers = helpers;


                this.options = {};
                this.configure(presetName);

                if (options) {
                    this.set(options);
                }
            }


            /** chainable
             * MarkdownIt.set(options)
             *
             * Set parser options (in the same format as in constructor). Probably, you
             * will never need it, but you can change options after constructor call.
             *
             * ##### Example
             *
             * ```javascript
             * var md = require('markdown-it')()
             *             .set({ html: true, breaks: true })
             *             .set({ typographer, true });
             * ```
             *
             * __Note:__ To achieve the best possible performance, don't modify a
             * `markdown-it` instance options on the fly. If you need multiple configurations
             * it's best to create multiple instances and initialize each with separate
             * config.
             **/
            MarkdownIt.prototype.set = function (options) {
                utils.assign(this.options, options);
                return this;
            };


            /** chainable, internal
             * MarkdownIt.configure(presets)
             *
             * Batch load of all options and compenent settings. This is internal method,
             * and you probably will not need it. But if you with - see available presets
             * and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)
             *
             * We strongly recommend to use presets instead of direct config loads. That
             * will give better compatibility with next versions.
             **/
            MarkdownIt.prototype.configure = function (presets) {
                var self = this, presetName;

                if (utils.isString(presets)) {
                    presetName = presets;
                    presets = config[presetName];
                    if (!presets) {
                        throw new Error('Wrong `markdown-it` preset "' + presetName + '", check name');
                    }
                }

                if (!presets) {
                    throw new Error('Wrong `markdown-it` preset, can\'t be empty');
                }

                if (presets.options) {
                    self.set(presets.options);
                }

                if (presets.components) {
                    Object.keys(presets.components).forEach(function (name) {
                        if (presets.components[name].rules) {
                            self[name].ruler.enableOnly(presets.components[name].rules);
                        }
                    });
                }
                return this;
            };


            /** chainable
             * MarkdownIt.enable(list, ignoreInvalid)
             * - list (String|Array): rule name or list of rule names to enable
             * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
             *
             * Enable list or rules. It will automatically find appropriate components,
             * containing rules with given names. If rule not found, and `ignoreInvalid`
             * not set - throws exception.
             *
             * ##### Example
             *
             * ```javascript
             * var md = require('markdown-it')()
             *             .enable(['sub', 'sup'])
             *             .disable('smartquotes');
             * ```
             **/
            MarkdownIt.prototype.enable = function (list, ignoreInvalid) {
                var result = [];

                if (!Array.isArray(list)) {
                    list = [list];
                }

                ['core', 'block', 'inline'].forEach(function (chain) {
                    result = result.concat(this[chain].ruler.enable(list, true));
                }, this);

                var missed = list.filter(function (name) {
                    return result.indexOf(name) < 0;
                });

                if (missed.length && !ignoreInvalid) {
                    throw new Error('MarkdownIt. Failed to enable unknown rule(s): ' + missed);
                }

                return this;
            };


            /** chainable
             * MarkdownIt.disable(list, ignoreInvalid)
             * - list (String|Array): rule name or list of rule names to disable.
             * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
             *
             * The same as [[MarkdownIt.enable]], but turn specified rules off.
             **/
            MarkdownIt.prototype.disable = function (list, ignoreInvalid) {
                var result = [];

                if (!Array.isArray(list)) {
                    list = [list];
                }

                ['core', 'block', 'inline'].forEach(function (chain) {
                    result = result.concat(this[chain].ruler.disable(list, true));
                }, this);

                var missed = list.filter(function (name) {
                    return result.indexOf(name) < 0;
                });

                if (missed.length && !ignoreInvalid) {
                    throw new Error('MarkdownIt. Failed to disable unknown rule(s): ' + missed);
                }
                return this;
            };


            /** chainable
             * MarkdownIt.use(plugin, params)
             *
             * Load specified plugin with given params into current parser instance.
             * It's just a sugar to call `plugin(md, params)` with curring.
             *
             * ##### Example
             *
             * ```javascript
             * var iterator = require('markdown-it-for-inline');
             * var md = require('markdown-it')()
             *             .use(iterator, 'foo_replace', 'text', function (tokens, idx) {
 *               tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');
 *             });
             * ```
             **/
            MarkdownIt.prototype.use = function (plugin /*, params, ... */) {
                var args = [this].concat(Array.prototype.slice.call(arguments, 1));
                plugin.apply(plugin, args);
                return this;
            };


            /** internal
             * MarkdownIt.parse(src, env) -> Array
             * - src (String): source string
             * - env (Object): environment sandbox
             *
             * Parse input string and returns list of block tokens (special token type
             * "inline" will contain list of inline tokens). You should not call this
             * method directly, until you write custom renderer (for example, to produce
             * AST).
             *
             * `env` is used to pass data between "distributed" rules (`{}` by default).
             * For example, references are parsed in different chains, and need sandbox
             * to store intermediate results. Can be used to inject data in specific cases.
             * You will not need it with high probability.
             **/
            MarkdownIt.prototype.parse = function (src, env) {
                var state = new this.core.State(src, this, env);

                this.core.process(state);

                return state.tokens;
            };


            /**
             * MarkdownIt.render(src [, env]) -> String
             * - src (String): source string
             * - env (Object): environment sandbox
             *
             * Render markdown string into html. It does all magic for you :).
             *
             * `env` can be used to inject additional metadata (`{}` by default).
             * But you will not need it with high probability. See also comment
             * in [[MarkdownIt.parse]].
             **/
            MarkdownIt.prototype.render = function (src, env) {
                env = env || {};

                return this.renderer.render(this.parse(src, env), this.options, env);
            };


            /** internal
             * MarkdownIt.parseInline(src, env) -> Array
             * - src (String): source string
             * - env (Object): environment sandbox
             *
             * The same as [[MarkdownIt.parse]] but skip all block rules. It returns the
             * block tokens list with th single `inline` element, containing parsed inline
             * tokens in `children` property.
             **/
            MarkdownIt.prototype.parseInline = function (src, env) {
                var state = new this.core.State(src, this, env);

                state.inlineMode = true;
                this.core.process(state);

                return state.tokens;
            };


            /**
             * MarkdownIt.renderInline(src [, env]) -> String
             * - src (String): source string
             * - env (Object): environment sandbox
             *
             * Similar to [[MarkdownIt.render]] but for single paragraph content. Result
             * will NOT be wrapped into `<p>` tags.
             **/
            MarkdownIt.prototype.renderInline = function (src, env) {
                env = env || {};

                return this.renderer.render(this.parseInline(src, env), this.options, env);
            };


            module.exports = MarkdownIt;

        }, {
            "./common/utils": 5,
            "./helpers": 6,
            "./parser_block": 12,
            "./parser_core": 13,
            "./parser_inline": 14,
            "./presets/commonmark": 15,
            "./presets/default": 16,
            "./presets/zero": 17,
            "./renderer": 18
        }],
        12: [function (require, module, exports) {
            /** internal
             * class ParserBlock
             *
             * Block-level tokenizer.
             **/
            'use strict';


            var Ruler = require('./ruler');


            var _rules = [
                ['code', require('./rules_block/code')],
                ['fence', require('./rules_block/fence'), ['paragraph', 'reference', 'blockquote', 'list']],
                ['blockquote', require('./rules_block/blockquote'), ['paragraph', 'reference', 'blockquote', 'list']],
                ['hr', require('./rules_block/hr'), ['paragraph', 'reference', 'blockquote', 'list']],
                ['list', require('./rules_block/list'), ['paragraph', 'reference', 'blockquote']],
                ['reference', require('./rules_block/reference'), ['reference']],
                ['heading', require('./rules_block/heading'), ['paragraph', 'reference', 'blockquote']],
                ['lheading', require('./rules_block/lheading')],
                ['html_block', require('./rules_block/html_block'), ['paragraph', 'reference', 'blockquote']],
                ['table', require('./rules_block/table'), ['paragraph', 'reference']],
                ['paragraph', require('./rules_block/paragraph')]
            ];


            /**
             * new ParserBlock()
             **/
            function ParserBlock() {
                /**
                 * ParserBlock#ruler -> Ruler
                 *
                 * [[Ruler]] instance. Keep configuration of block rules.
                 **/
                this.ruler = new Ruler();

                for (var i = 0; i < _rules.length; i++) {
                    this.ruler.push(_rules[i][0], _rules[i][1], {alt: (_rules[i][2] || []).slice()});
                }
            }


// Generate tokens for input range
//
            ParserBlock.prototype.tokenize = function (state, startLine, endLine) {
                var ok, i,
                    rules = this.ruler.getRules(''),
                    len = rules.length,
                    line = startLine,
                    hasEmptyLines = false,
                    maxNesting = state.md.options.maxNesting;

                while (line < endLine) {
                    state.line = line = state.skipEmptyLines(line);
                    if (line >= endLine) {
                        break;
                    }

                    // Termination condition for nested calls.
                    // Nested calls currently used for blockquotes & lists
                    if (state.tShift[line] < state.blkIndent) {
                        break;
                    }

                    // If nesting level exceeded - skip tail to the end. That's not ordinary
                    // situation and we should not care about content.
                    if (state.level >= maxNesting) {
                        state.line = endLine;
                        break;
                    }

                    // Try all possible rules.
                    // On success, rule should:
                    //
                    // - update `state.line`
                    // - update `state.tokens`
                    // - return true

                    for (i = 0; i < len; i++) {
                        ok = rules[i](state, line, endLine, false);
                        if (ok) {
                            break;
                        }
                    }

                    // set state.tight iff we had an empty line before current tag
                    // i.e. latest empty line should not count
                    state.tight = !hasEmptyLines;

                    // paragraph might "eat" one newline after it in nested lists
                    if (state.isEmpty(state.line - 1)) {
                        hasEmptyLines = true;
                    }

                    line = state.line;

                    if (line < endLine && state.isEmpty(line)) {
                        hasEmptyLines = true;
                        line++;

                        // two empty lines should stop the parser in list mode
                        if (line < endLine && state.parentType === 'list' && state.isEmpty(line)) {
                            break;
                        }
                        state.line = line;
                    }
                }
            };


            /**
             * ParserBlock.parse(str, md, env, outTokens)
             *
             * Process input string and push block tokens into `outTokens`
             **/
            ParserBlock.prototype.parse = function (src, md, env, outTokens) {
                var state;

                if (!src) {
                    return [];
                }

                state = new this.State(src, md, env, outTokens);

                this.tokenize(state, state.line, state.lineMax);
            };


            ParserBlock.prototype.State = require('./rules_block/state_block');


            module.exports = ParserBlock;

        }, {
            "./ruler": 19,
            "./rules_block/blockquote": 20,
            "./rules_block/code": 21,
            "./rules_block/fence": 22,
            "./rules_block/heading": 23,
            "./rules_block/hr": 24,
            "./rules_block/html_block": 25,
            "./rules_block/lheading": 26,
            "./rules_block/list": 27,
            "./rules_block/paragraph": 28,
            "./rules_block/reference": 29,
            "./rules_block/state_block": 30,
            "./rules_block/table": 31
        }],
        13: [function (require, module, exports) {
            /** internal
             * class Core
             *
             * Top-level rules executor. Glues block/inline parsers and does intermediate
             * transformations.
             **/
            'use strict';


            var Ruler = require('./ruler');


            var _rules = [
                ['normalize', require('./rules_core/normalize')],
                ['block', require('./rules_core/block')],
                ['inline', require('./rules_core/inline')],
                ['replacements', require('./rules_core/replacements')],
                ['smartquotes', require('./rules_core/smartquotes')],
                ['linkify', require('./rules_core/linkify')]
            ];


            /**
             * new Core()
             **/
            function Core() {
                /**
                 * Core#ruler -> Ruler
                 *
                 * [[Ruler]] instance. Keep configuration of core rules.
                 **/
                this.ruler = new Ruler();

                for (var i = 0; i < _rules.length; i++) {
                    this.ruler.push(_rules[i][0], _rules[i][1]);
                }
            }


            /**
             * Core.process(state)
             *
             * Executes core chain rules.
             **/
            Core.prototype.process = function (state) {
                var i, l, rules;

                rules = this.ruler.getRules('');

                for (i = 0, l = rules.length; i < l; i++) {
                    rules[i](state);
                }
            };

            Core.prototype.State = require('./rules_core/state_core');


            module.exports = Core;

        }, {
            "./ruler": 19,
            "./rules_core/block": 32,
            "./rules_core/inline": 33,
            "./rules_core/linkify": 34,
            "./rules_core/normalize": 35,
            "./rules_core/replacements": 36,
            "./rules_core/smartquotes": 37,
            "./rules_core/state_core": 38
        }],
        14: [function (require, module, exports) {
            /** internal
             * class ParserInline
             *
             * Tokenizes paragraph content.
             **/
            'use strict';


            var Ruler = require('./ruler');
            var replaceEntities = require('./common/utils').replaceEntities;

////////////////////////////////////////////////////////////////////////////////
// Parser rules

            var _rules = [
                ['text', require('./rules_inline/text')],
                ['newline', require('./rules_inline/newline')],
                ['escape', require('./rules_inline/escape')],
                ['backticks', require('./rules_inline/backticks')],
                ['strikethrough', require('./rules_inline/strikethrough')],
                ['emphasis', require('./rules_inline/emphasis')],
                ['link', require('./rules_inline/link')],
                ['image', require('./rules_inline/image')],
                ['autolink', require('./rules_inline/autolink')],
                ['html_inline', require('./rules_inline/html_inline')],
                ['entity', require('./rules_inline/entity')]
            ];


            var BAD_PROTOCOLS = ['vbscript', 'javascript', 'file'];

            function validateLink(url) {
                var str = url.trim().toLowerCase();

                // Care about digital entities "javascript&#x3A;alert(1)"
                str = replaceEntities(str);

                if (str.indexOf(':') >= 0 && BAD_PROTOCOLS.indexOf(str.split(':')[0]) >= 0) {
                    return false;
                }
                return true;
            }


            /**
             * new ParserInline()
             **/
            function ParserInline() {
                /**
                 * ParserInline#validateLink(url) -> Boolean
                 *
                 * Link validation function. CommonMark allows too much in links. By default
                 * we disable `javascript:` and `vbscript:` schemas. You can change this
                 * behaviour.
                 *
                 * ```javascript
                 * var md = require('markdown-it')();
                 * // enable everything
                 * md.inline.validateLink = function () { return true; }
                 * ```
                 **/
                this.validateLink = validateLink;

                /**
                 * ParserInline#ruler -> Ruler
                 *
                 * [[Ruler]] instance. Keep configuration of inline rules.
                 **/
                this.ruler = new Ruler();

                for (var i = 0; i < _rules.length; i++) {
                    this.ruler.push(_rules[i][0], _rules[i][1]);
                }
            }


// Skip single token by running all rules in validation mode;
// returns `true` if any rule reported success
//
            ParserInline.prototype.skipToken = function (state) {
                var i, cached_pos, pos = state.pos,
                    rules = this.ruler.getRules(''),
                    len = rules.length,
                    maxNesting = state.md.options.maxNesting;


                if ((cached_pos = state.cacheGet(pos)) > 0) {
                    state.pos = cached_pos;
                    return;
                }

                if (state.level < maxNesting) {
                    for (i = 0; i < len; i++) {
                        if (rules[i](state, true)) {
                            state.cacheSet(pos, state.pos);
                            return;
                        }
                    }
                    state.pos++;

                } else {
                    // If nesting level exceeded - skip tail to the end. That's not ordinary
                    // situation and we should not care about content.
                    state.pos = state.max;
                }

                state.cacheSet(pos, state.pos);
            };


// Generate tokens for input range
//
            ParserInline.prototype.tokenize = function (state) {
                var ok, i,
                    rules = this.ruler.getRules(''),
                    len = rules.length,
                    end = state.posMax,
                    maxNesting = state.md.options.maxNesting;

                while (state.pos < end) {

                    // If nesting level exceeded - skip tail to the end. That's not ordinary
                    // situation and we should not care about content.
                    if (state.level >= maxNesting) {
                        state.pos = end;
                        break;
                    }
                    // Try all possible rules.
                    // On success, rule should:
                    //
                    // - update `state.pos`
                    // - update `state.tokens`
                    // - return true

                    for (i = 0; i < len; i++) {
                        ok = rules[i](state, false);
                        if (ok) {
                            break;
                        }
                    }

                    if (ok) {
                        if (state.pos >= end) {
                            break;
                        }
                        continue;
                    }

                    state.pending += state.src[state.pos++];
                }

                if (state.pending) {
                    state.pushPending();
                }
            };


            /**
             * ParserInline.parse(str, md, env, outTokens)
             *
             * Process input string and push inline tokens into `outTokens`
             **/
            ParserInline.prototype.parse = function (str, md, env, outTokens) {
                var state = new this.State(str, md, env, outTokens);

                this.tokenize(state);
            };


            ParserInline.prototype.State = require('./rules_inline/state_inline');


            module.exports = ParserInline;

        }, {
            "./common/utils": 5,
            "./ruler": 19,
            "./rules_inline/autolink": 39,
            "./rules_inline/backticks": 40,
            "./rules_inline/emphasis": 41,
            "./rules_inline/entity": 42,
            "./rules_inline/escape": 43,
            "./rules_inline/html_inline": 44,
            "./rules_inline/image": 45,
            "./rules_inline/link": 46,
            "./rules_inline/newline": 47,
            "./rules_inline/state_inline": 48,
            "./rules_inline/strikethrough": 49,
            "./rules_inline/text": 50
        }],
        15: [function (require, module, exports) {
// Commonmark default options

            'use strict';


            module.exports = {
                options: {
                    html: false,         // Enable HTML tags in source
                    xhtmlOut: true,         // Use '/' to close single tags (<br />)
                    breaks: true,        // Convert '\n' in paragraphs into <br>
                    langPrefix: 'language-',  // CSS language prefix for fenced blocks
                    linkify: true,        // autoconvert URL-like texts to links

                    // Enable some language-neutral replacements + quotes beautification
                    typographer: false,

                    // Double + single quotes replacement pairs, when typographer enabled,
                    // and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
                    quotes: '\u201c\u201d\u2018\u2019' /* “”‘’ */,

                    // Highlighter function. Should return escaped HTML,
                    // or '' if input not changed
                    //
                    // function (/*str, lang*/) { return ''; }
                    //
                    highlight: null,

                    maxNesting: 20            // Internal protection, recursion limit
                },

                components: {

                    core: {
                        rules: [
                            'normalize',
                            'block',
                            'inline'
                        ]
                    },

                    block: {
                        rules: [
                            'blockquote',
                            'code',
                            'fence',
                            'heading',
                            'hr',
                            'html_block',
                            'lheading',
                            'list',
                            'reference',
                            'paragraph'
                        ]
                    },

                    inline: {
                        rules: [
                            'autolink',
                            'backticks',
                            'emphasis',
                            'entity',
                            'escape',
                            'html_inline',
                            'image',
                            'link',
                            'newline',
                            'text'
                        ]
                    }
                }
            };

        }, {}],
        16: [function (require, module, exports) {
// markdown-it default options

            'use strict';


            module.exports = {
                options: {
                    html: false,        // Enable HTML tags in source
                    xhtmlOut: false,        // Use '/' to close single tags (<br />)
                    breaks: true,        // Convert '\n' in paragraphs into <br>
                    langPrefix: 'language-',  // CSS language prefix for fenced blocks
                    linkify: true,        // autoconvert URL-like texts to links

                    // Enable some language-neutral replacements + quotes beautification
                    typographer: false,

                    // Double + single quotes replacement pairs, when typographer enabled,
                    // and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
                    quotes: '\u201c\u201d\u2018\u2019' /* “”‘’ */,

                    // Highlighter function. Should return escaped HTML,
                    // or '' if input not changed
                    //
                    // function (/*str, lang*/) { return ''; }
                    //
                    highlight: null,

                    maxNesting: 20            // Internal protection, recursion limit
                },

                components: {

                    core: {},
                    block: {},
                    inline: {}
                }
            };

        }, {}],
        17: [function (require, module, exports) {
// "Zero" preset, with nothing enabled. Useful for manual configuring of simple
// modes. For example, to parse bold/italic only.

            'use strict';


            module.exports = {
                options: {
                    html: false,        // Enable HTML tags in source
                    xhtmlOut: false,        // Use '/' to close single tags (<br />)
                    breaks: true,        // Convert '\n' in paragraphs into <br>
                    langPrefix: 'language-',  // CSS language prefix for fenced blocks
                    linkify: true,        // autoconvert URL-like texts to links

                    // Enable some language-neutral replacements + quotes beautification
                    typographer: false,

                    // Double + single quotes replacement pairs, when typographer enabled,
                    // and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
                    quotes: '\u201c\u201d\u2018\u2019' /* “”‘’ */,

                    // Highlighter function. Should return escaped HTML,
                    // or '' if input not changed
                    //
                    // function (/*str, lang*/) { return ''; }
                    //
                    highlight: null,

                    maxNesting: 20            // Internal protection, recursion limit
                },

                components: {

                    core: {
                        rules: [
                            'normalize',
                            'block',
                            'inline'
                        ]
                    },

                    block: {
                        rules: [
                            'paragraph'
                        ]
                    },

                    inline: {
                        rules: [
                            'text'
                        ]
                    }
                }
            };

        }, {}],
        18: [function (require, module, exports) {
            /**
             * class Renderer
             *
             * Generates HTML from parsed token stream. Each instance has independent
             * copy of rules. Those can be rewritten with ease. Also, you can add new
             * rules if you create plugin and adds new token types.
             **/
            'use strict';


            var assign = require('./common/utils').assign;
            var unescapeMd = require('./common/utils').unescapeMd;
            var replaceEntities = require('./common/utils').replaceEntities;
            var escapeHtml = require('./common/utils').escapeHtml;


////////////////////////////////////////////////////////////////////////////////

            var rules = {};


            rules.blockquote_open = function () {
                return '<blockquote>\n';
            };
            rules.blockquote_close = function () {
                return '</blockquote>\n';
            };


            rules.code_block = function (tokens, idx /*, options, env */) {
                return '<pre><code>' + escapeHtml(tokens[idx].content) + '</code></pre>\n';
            };
            rules.code_inline = function (tokens, idx /*, options, env */) {
                return '<code>' + escapeHtml(tokens[idx].content) + '</code>';
            };


            rules.fence = function (tokens, idx, options /*, env, self*/) {
                var token = tokens[idx];
                var langClass = '';
                var langPrefix = options.langPrefix;
                var langName = '';
                var highlighted;

                if (token.params) {
                    langName = escapeHtml(replaceEntities(unescapeMd(token.params.split(/\s+/g)[0])));
                    langClass = ' class="' + langPrefix + langName + '"';
                }

                if (options.highlight) {
                    highlighted = options.highlight(token.content, langName) || escapeHtml(token.content);
                } else {
                    highlighted = escapeHtml(token.content);
                }


                return '<pre><code' + langClass + '>'
                    + highlighted
                    + '</code></pre>\n';
            };


            rules.heading_open = function (tokens, idx /*, options, env */) {
                return '<h' + tokens[idx].hLevel + '>';
            };
            rules.heading_close = function (tokens, idx /*, options, env */) {
                return '</h' + tokens[idx].hLevel + '>\n';
            };


            rules.hr = function (tokens, idx, options /*, env */) {
                return (options.xhtmlOut ? '<hr />\n' : '<hr>\n');
            };


            rules.bullet_list_open = function () {
                return '<ul>\n';
            };
            rules.bullet_list_close = function () {
                return '</ul>\n';
            };
            rules.list_item_open = function (tokens, idx /*, options, env */) {
                var next = tokens[idx + 1];
                if ((next.type === 'list_item_close') ||
                    (next.type === 'paragraph_open' && next.tight)) {
                    return '<li>';
                }
                return '<li>\n';
            };
            rules.list_item_close = function () {
                return '</li>\n';
            };
            rules.ordered_list_open = function (tokens, idx /*, options, env */) {
                if (tokens[idx].order > 1) {
                    return '<ol start="' + tokens[idx].order + '">\n';
                }
                return '<ol>\n';
            };
            rules.ordered_list_close = function () {
                return '</ol>\n';
            };


            rules.paragraph_open = function (tokens, idx /*, options, env */) {
                return tokens[idx].tight ? '' : '<p>';
            };
            rules.paragraph_close = function (tokens, idx /*, options, env */) {
                if (tokens[idx].tight === true) {
                    return tokens[idx + 1].type.slice(-5) === 'close' ? '' : '\n';
                }
                return '</p>\n';
            };


            rules.link_open = function (tokens, idx /*, options, env */) {
                var title = tokens[idx].title ? (' title="' + escapeHtml(replaceEntities(tokens[idx].title)) + '"') : '';
                var target = tokens[idx].target ? (' target="' + escapeHtml(tokens[idx].target) + '"') : '';
                return '<a href="' + escapeHtml(tokens[idx].href) + '"' + title + target + '>';
            };
            rules.link_close = function (/* tokens, idx, options, env */) {
                return '</a>';
            };


            rules.image = function (tokens, idx, options, env, self) {
                var src = ' src="' + escapeHtml(tokens[idx].src) + '"';
                var title = tokens[idx].title ? (' title="' + escapeHtml(replaceEntities(tokens[idx].title)) + '"') : '';
                var alt = ' alt="' + self.renderInlineAsText(tokens[idx].tokens, options, env) + '"';
                var suffix = options.xhtmlOut ? ' /' : '';
                return '<img' + src + alt + title + suffix + '>';
            };


            rules.table_open = function () {
                return '<table>\n';
            };
            rules.table_close = function () {
                return '</table>\n';
            };
            rules.thead_open = function () {
                return '<thead>\n';
            };
            rules.thead_close = function () {
                return '</thead>\n';
            };
            rules.tbody_open = function () {
                return '<tbody>\n';
            };
            rules.tbody_close = function () {
                return '</tbody>\n';
            };
            rules.tr_open = function () {
                return '<tr>';
            };
            rules.tr_close = function () {
                return '</tr>\n';
            };
            rules.th_open = function (tokens, idx /*, options, env */) {
                if (tokens[idx].align) {
                    return '<th style="text-align:' + tokens[idx].align + '">';
                }
                return '<th>';
            };
            rules.th_close = function () {
                return '</th>';
            };
            rules.td_open = function (tokens, idx /*, options, env */) {
                if (tokens[idx].align) {
                    return '<td style="text-align:' + tokens[idx].align + '">';
                }
                return '<td>';
            };
            rules.td_close = function () {
                return '</td>';
            };


            rules.strong_open = function () {
                return '<strong>';
            };
            rules.strong_close = function () {
                return '</strong>';
            };


            rules.em_open = function () {
                return '<em>';
            };
            rules.em_close = function () {
                return '</em>';
            };


            rules.s_open = function () {
                return '<s>';
            };
            rules.s_close = function () {
                return '</s>';
            };


            rules.hardbreak = function (tokens, idx, options /*, env */) {
                return options.xhtmlOut ? '<br />\n' : '<br>\n';
            };
            rules.softbreak = function (tokens, idx, options /*, env */) {
                return options.breaks ? (options.xhtmlOut ? '<br />\n' : '<br>\n') : '\n';
            };


            rules.text = function (tokens, idx /*, options, env */) {
                return escapeHtml(tokens[idx].content);
            };


            rules.html_block = function (tokens, idx /*, options, env */) {
                return tokens[idx].content;
            };
            rules.html_inline = function (tokens, idx /*, options, env */) {
                return tokens[idx].content;
            };


            /**
             * new Renderer()
             *
             * Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults.
             **/
            function Renderer() {

                /**
                 * Renderer#rules -> Object
                 *
                 * Contains render rules for tokens. Can be updated and extended.
                 *
                 * ##### Example
                 *
                 * ```javascript
                 * var md = require('markdown-it')();
                 *
                 * md.renderer.rules.strong_open  = function () { return '<b>'; };
                 * md.renderer.rules.strong_close = function () { return '</b>'; };
                 *
                 * var result = md.renderInline(...);
                 * ```
                 *
                 * Each rule is called as independed static function with fixed signature:
                 *
                 * ```javascript
                 * function my_token_render(tokens, idx, options, env, renderer) {
   *   // ...
   *   return renderedHTML;
   * }
                 * ```
                 *
                 * See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js)
                 * for more details and examples.
                 **/
                this.rules = assign({}, rules);
            }


            /**
             * Renderer.renderInline(tokens, options, env) -> String
             * - tokens (Array): list on block tokens to renter
             * - options (Object): params of parser instance
             * - env (Object): additional data from parsed input (references, for example)
             *
             * The same as [[Renderer.render]], but for single token of `inline` type.
             **/
            Renderer.prototype.renderInline = function (tokens, options, env) {
                var result = '',
                    _rules = this.rules;

                for (var i = 0, len = tokens.length; i < len; i++) {
                    result += _rules[tokens[i].type](tokens, i, options, env, this);
                }

                return result;
            };


            /** internal
             * Renderer.renderInlineAsText(tokens, options, env) -> String
             * - tokens (Array): list on block tokens to renter
             * - options (Object): params of parser instance
             * - env (Object): additional data from parsed input (references, for example)
             *
             * Special kludge for image `alt` attributes to conform CommonMark spec.
             * Don't try to use it! Spec requires to show `alt` content with stripped markup,
             * instead of simple escaping.
             **/
            Renderer.prototype.renderInlineAsText = function (tokens, options, env) {
                var result = '',
                    _rules = this.rules;

                for (var i = 0, len = tokens.length; i < len; i++) {
                    if (tokens[i].type === 'text') {
                        result += _rules.text(tokens, i, options, env, this);
                    } else if (tokens[i].type === 'image') {
                        result += this.renderInlineAsText(tokens[i].tokens, options, env);
                    }
                }

                return result;
            };


            /**
             * Renderer.render(tokens, options, env) -> String
             * - tokens (Array): list on block tokens to renter
             * - options (Object): params of parser instance
             * - env (Object): additional data from parsed input (references, for example)
             *
             * Takes token stream and generates HTML. Probably, you will never need to call
             * this method directly.
             **/
            Renderer.prototype.render = function (tokens, options, env) {
                var i, len,
                    result = '',
                    _rules = this.rules;

                for (i = 0, len = tokens.length; i < len; i++) {
                    if (tokens[i].type === 'inline') {
                        result += this.renderInline(tokens[i].children, options, env);
                    } else {
                        result += _rules[tokens[i].type](tokens, i, options, env, this);
                    }
                }

                return result;
            };

            module.exports = Renderer;

        }, {"./common/utils": 5}],
        19: [function (require, module, exports) {
            /**
             * class Ruler
             *
             * Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and
             * [[MarkdownIt#inline]] to manage sequences of functions (rules):
             *
             * - keep rules in defined order
             * - assign the name to each rule
             * - enable/disable rules
             * - add/replace rules
             * - allow assign rules to additional named chains (in the same)
             * - cacheing lists of active rules
             *
             * You will not need use this class directly until write plugins. For simple
             * rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and
             * [[MarkdownIt.use]].
             **/
            'use strict';


            /**
             * new Ruler()
             **/
            function Ruler() {
                // List of added rules. Each element is:
                //
                // {
                //   name: XXX,
                //   enabled: Boolean,
                //   fn: Function(),
                //   alt: [ name2, name3 ]
                // }
                //
                this.__rules__ = [];

                // Cached rule chains.
                //
                // First level - chain name, '' for default.
                // Second level - diginal anchor for fast filtering by charcodes.
                //
                this.__cache__ = null;
            }

////////////////////////////////////////////////////////////////////////////////
// Helper methods, should not be used directly


// Find rule index by name
//
            Ruler.prototype.__find__ = function (name) {
                for (var i = 0; i < this.__rules__.length; i++) {
                    if (this.__rules__[i].name === name) {
                        return i;
                    }
                }
                return -1;
            };


// Build rules lookup cache
//
            Ruler.prototype.__compile__ = function () {
                var self = this;
                var chains = [''];

                // collect unique names
                self.__rules__.forEach(function (rule) {
                    if (!rule.enabled) {
                        return;
                    }

                    rule.alt.forEach(function (altName) {
                        if (chains.indexOf(altName) < 0) {
                            chains.push(altName);
                        }
                    });
                });

                self.__cache__ = {};

                chains.forEach(function (chain) {
                    self.__cache__[chain] = [];
                    self.__rules__.forEach(function (rule) {
                        if (!rule.enabled) {
                            return;
                        }

                        if (chain && rule.alt.indexOf(chain) < 0) {
                            return;
                        }

                        self.__cache__[chain].push(rule.fn);
                    });
                });
            };


            /**
             * Ruler.at(name, fn [, options])
             * - name (String): rule name to replace.
             * - fn (Function): new rule function.
             * - options (Object): new rule options (not mandatory).
             *
             * Replace rule by name with new function & options. Throws error if name not
             * found.
             *
             * ##### Options:
             *
             * - __alt__ - array with names of "alternate" chains.
             *
             * ##### Example
             *
             * Replace existing typorgapher replacement rule with new one:
             *
             * ```javascript
             * var md = require('markdown-it')();
             *
             * md.core.ruler.at('replacements', function replace(state) {
 *   //...
 * });
             * ```
             **/
            Ruler.prototype.at = function (name, fn, options) {
                var index = this.__find__(name);
                var opt = options || {};

                if (index === -1) {
                    throw new Error('Parser rule not found: ' + name);
                }

                this.__rules__[index].fn = fn;
                this.__rules__[index].alt = opt.alt || [];
                this.__cache__ = null;
            };


            /**
             * Ruler.before(beforeName, ruleName, fn [, options])
             * - beforeName (String): new rule will be added before this one.
             * - ruleName (String): name of added rule.
             * - fn (Function): rule function.
             * - options (Object): rule options (not mandatory).
             *
             * Add new rule to chain before one with given name. See also
             * [[Ruler.after]], [[Ruler.push]].
             *
             * ##### Options:
             *
             * - __alt__ - array with names of "alternate" chains.
             *
             * ##### Example
             *
             * ```javascript
             * var md = require('markdown-it')();
             *
             * md.block.ruler.before('paragraph', 'my_rule', function replace(state) {
 *   //...
 * });
             * ```
             **/
            Ruler.prototype.before = function (beforeName, ruleName, fn, options) {
                var index = this.__find__(beforeName);
                var opt = options || {};

                if (index === -1) {
                    throw new Error('Parser rule not found: ' + beforeName);
                }

                this.__rules__.splice(index, 0, {
                    name: ruleName,
                    enabled: true,
                    fn: fn,
                    alt: opt.alt || []
                });

                this.__cache__ = null;
            };


            /**
             * Ruler.after(afterName, ruleName, fn [, options])
             * - afterName (String): new rule will be added after this one.
             * - ruleName (String): name of added rule.
             * - fn (Function): rule function.
             * - options (Object): rule options (not mandatory).
             *
             * Add new rule to chain after one with given name. See also
             * [[Ruler.before]], [[Ruler.push]].
             *
             * ##### Options:
             *
             * - __alt__ - array with names of "alternate" chains.
             *
             * ##### Example
             *
             * ```javascript
             * var md = require('markdown-it')();
             *
             * md.inline.ruler.after('text', 'my_rule', function replace(state) {
 *   //...
 * });
             * ```
             **/
            Ruler.prototype.after = function (afterName, ruleName, fn, options) {
                var index = this.__find__(afterName);
                var opt = options || {};

                if (index === -1) {
                    throw new Error('Parser rule not found: ' + afterName);
                }

                this.__rules__.splice(index + 1, 0, {
                    name: ruleName,
                    enabled: true,
                    fn: fn,
                    alt: opt.alt || []
                });

                this.__cache__ = null;
            };

            /**
             * Ruler.push(ruleName, fn [, options])
             * - ruleName (String): name of added rule.
             * - fn (Function): rule function.
             * - options (Object): rule options (not mandatory).
             *
             * Push new rule to the end of chain. See also
             * [[Ruler.before]], [[Ruler.after]].
             *
             * ##### Options:
             *
             * - __alt__ - array with names of "alternate" chains.
             *
             * ##### Example
             *
             * ```javascript
             * var md = require('markdown-it')();
             *
             * md.core.ruler.push('emphasis', 'my_rule', function replace(state) {
 *   //...
 * });
             * ```
             **/
            Ruler.prototype.push = function (ruleName, fn, options) {
                var opt = options || {};

                this.__rules__.push({
                    name: ruleName,
                    enabled: true,
                    fn: fn,
                    alt: opt.alt || []
                });

                this.__cache__ = null;
            };


            /**
             * Ruler.enable(list [, ignoreInvalid]) -> Array
             * - list (String|Array): list of rule names to enable.
             * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
             *
             * Enable rules with given names. If any rule name not found - throw Error.
             * Errors can be disabled by second param.
             *
             * Returns list of found rule names (if no exception happened).
             *
             * See also [[Ruler.disable]], [[Ruler.enableOnly]].
             **/
            Ruler.prototype.enable = function (list, ignoreInvalid) {
                if (!Array.isArray(list)) {
                    list = [list];
                }

                var result = [];

                // Search by name and enable
                list.forEach(function (name) {
                    var idx = this.__find__(name);

                    if (idx < 0) {
                        if (ignoreInvalid) {
                            return;
                        }
                        throw new Error('Rules manager: invalid rule name ' + name);
                    }
                    this.__rules__[idx].enabled = true;
                    result.push(name);
                }, this);

                this.__cache__ = null;
                return result;
            };


            /**
             * Ruler.enableOnly(list [, ignoreInvalid])
             * - list (String|Array): list of rule names to enable (whitelist).
             * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
             *
             * Enable rules with given names, and disable everything else. If any rule name
             * not found - throw Error. Errors can be disabled by second param.
             *
             * See also [[Ruler.disable]], [[Ruler.enable]].
             **/
            Ruler.prototype.enableOnly = function (list, ignoreInvalid) {
                if (!Array.isArray(list)) {
                    list = [list];
                }

                this.__rules__.forEach(function (rule) {
                    rule.enabled = false;
                });

                this.enable(list, ignoreInvalid);
            };


            /**
             * Ruler.disable(list [, ignoreInvalid]) -> Array
             * - list (String|Array): list of rule names to disable.
             * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
             *
             * Disable rules with given names. If any rule name not found - throw Error.
             * Errors can be disabled by second param.
             *
             * Returns list of found rule names (if no exception happened).
             *
             * See also [[Ruler.enable]], [[Ruler.enableOnly]].
             **/
            Ruler.prototype.disable = function (list, ignoreInvalid) {
                if (!Array.isArray(list)) {
                    list = [list];
                }

                var result = [];

                // Search by name and disable
                list.forEach(function (name) {
                    var idx = this.__find__(name);

                    if (idx < 0) {
                        if (ignoreInvalid) {
                            return;
                        }
                        throw new Error('Rules manager: invalid rule name ' + name);
                    }
                    this.__rules__[idx].enabled = false;
                    result.push(name);
                }, this);

                this.__cache__ = null;
                return result;
            };


            /**
             * Ruler.getRules(chainName) -> Array
             *
             * Return array of active functions (rules) for given chain name. It analyzes
             * rules configuration, compiles caches if not exists and returns result.
             *
             * Default chain name is `''` (empty string). It can't be skipped. That's
             * done intentionally, to keep signature monomorphic for high speed.
             **/
            Ruler.prototype.getRules = function (chainName) {
                if (this.__cache__ === null) {
                    this.__compile__();
                }

                // Chain can be empty, if rules disabled. But we still have to return Array.
                return this.__cache__[chainName] || [];
            };

            module.exports = Ruler;

        }, {}],
        20: [function (require, module, exports) {
// Block quotes

            'use strict';


            module.exports = function blockquote(state, startLine, endLine, silent) {
                var nextLine, lastLineEmpty, oldTShift, oldBMarks, oldIndent, oldParentType, lines,
                    terminatorRules,
                    i, l, terminate,
                    pos = state.bMarks[startLine] + state.tShift[startLine],
                    max = state.eMarks[startLine];

                if (pos > max) {
                    return false;
                }

                // check the block quote marker
                if (state.src.charCodeAt(pos++) !== 0x3E/* > */) {
                    return false;
                }

                // we know that it's going to be a valid blockquote,
                // so no point trying to find the end of it in silent mode
                if (silent) {
                    return true;
                }

                // skip one optional space after '>'
                if (state.src.charCodeAt(pos) === 0x20) {
                    pos++;
                }

                oldIndent = state.blkIndent;
                state.blkIndent = 0;

                oldBMarks = [state.bMarks[startLine]];
                state.bMarks[startLine] = pos;

                // check if we have an empty blockquote
                pos = pos < max ? state.skipSpaces(pos) : pos;
                lastLineEmpty = pos >= max;

                oldTShift = [state.tShift[startLine]];
                state.tShift[startLine] = pos - state.bMarks[startLine];

                terminatorRules = state.md.block.ruler.getRules('blockquote');

                // Search the end of the block
                //
                // Block ends with either:
                //  1. an empty line outside:
                //     ```
                //     > test
                //
                //     ```
                //  2. an empty line inside:
                //     ```
                //     >
                //     test
                //     ```
                //  3. another tag
                //     ```
                //     > test
                //      - - -
                //     ```
                for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {
                    pos = state.bMarks[nextLine] + state.tShift[nextLine];
                    max = state.eMarks[nextLine];

                    if (pos >= max) {
                        // Case 1: line is not inside the blockquote, and this line is empty.
                        break;
                    }

                    if (state.src.charCodeAt(pos++) === 0x3E/* > */) {
                        // This line is inside the blockquote.

                        // skip one optional space after '>'
                        if (state.src.charCodeAt(pos) === 0x20) {
                            pos++;
                        }

                        oldBMarks.push(state.bMarks[nextLine]);
                        state.bMarks[nextLine] = pos;

                        pos = pos < max ? state.skipSpaces(pos) : pos;
                        lastLineEmpty = pos >= max;

                        oldTShift.push(state.tShift[nextLine]);
                        state.tShift[nextLine] = pos - state.bMarks[nextLine];
                        continue;
                    }

                    // Case 2: line is not inside the blockquote, and the last line was empty.
                    if (lastLineEmpty) {
                        break;
                    }

                    // Case 3: another tag found.
                    terminate = false;
                    for (i = 0, l = terminatorRules.length; i < l; i++) {
                        if (terminatorRules[i](state, nextLine, endLine, true)) {
                            terminate = true;
                            break;
                        }
                    }
                    if (terminate) {
                        break;
                    }

                    oldBMarks.push(state.bMarks[nextLine]);
                    oldTShift.push(state.tShift[nextLine]);

                    // A negative number means that this is a paragraph continuation;
                    //
                    // Any negative number will do the job here, but it's better for it
                    // to be large enough to make any bugs obvious.
                    state.tShift[nextLine] = -1337;
                }

                oldParentType = state.parentType;
                state.parentType = 'blockquote';
                state.tokens.push({
                    type: 'blockquote_open',
                    lines: lines = [startLine, 0],
                    level: state.level++
                });
                state.md.block.tokenize(state, startLine, nextLine);
                state.tokens.push({
                    type: 'blockquote_close',
                    level: --state.level
                });
                state.parentType = oldParentType;
                lines[1] = state.line;

                // Restore original tShift; this might not be necessary since the parser
                // has already been here, but just to make sure we can do that.
                for (i = 0; i < oldTShift.length; i++) {
                    state.bMarks[i + startLine] = oldBMarks[i];
                    state.tShift[i + startLine] = oldTShift[i];
                }
                state.blkIndent = oldIndent;

                return true;
            };

        }, {}],
        21: [function (require, module, exports) {
// Code block (4 spaces padded)

            'use strict';


            module.exports = function code(state, startLine, endLine/*, silent*/) {
                var nextLine, last;

                if (state.tShift[startLine] - state.blkIndent < 4) {
                    return false;
                }

                last = nextLine = startLine + 1;

                while (nextLine < endLine) {
                    if (state.isEmpty(nextLine)) {
                        nextLine++;
                        continue;
                    }
                    if (state.tShift[nextLine] - state.blkIndent >= 4) {
                        nextLine++;
                        last = nextLine;
                        continue;
                    }
                    break;
                }

                state.line = nextLine;
                state.tokens.push({
                    type: 'code_block',
                    content: state.getLines(startLine, last, 4 + state.blkIndent, true),
                    lines: [startLine, state.line],
                    level: state.level
                });

                return true;
            };

        }, {}],
        22: [function (require, module, exports) {
// fences (``` lang, ~~~ lang)

            'use strict';


            module.exports = function fence(state, startLine, endLine, silent) {
                var marker, len, params, nextLine, mem,
                    haveEndMarker = false,
                    pos = state.bMarks[startLine] + state.tShift[startLine],
                    max = state.eMarks[startLine];

                if (pos + 3 > max) {
                    return false;
                }

                marker = state.src.charCodeAt(pos);

                if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) {
                    return false;
                }

                // scan marker length
                mem = pos;
                pos = state.skipChars(pos, marker);

                len = pos - mem;

                if (len < 3) {
                    return false;
                }

                params = state.src.slice(pos, max).trim();

                if (params.indexOf('`') >= 0) {
                    return false;
                }

                // Since start is found, we can report success here in validation mode
                if (silent) {
                    return true;
                }

                // search end of block
                nextLine = startLine;

                for (; ;) {
                    nextLine++;
                    if (nextLine >= endLine) {
                        // unclosed block should be autoclosed by end of document.
                        // also block seems to be autoclosed by end of parent
                        break;
                    }

                    pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];
                    max = state.eMarks[nextLine];

                    if (pos < max && state.tShift[nextLine] < state.blkIndent) {
                        // non-empty line with negative indent should stop the list:
                        // - ```
                        //  test
                        break;
                    }

                    if (state.src.charCodeAt(pos) !== marker) {
                        continue;
                    }

                    if (state.tShift[nextLine] - state.blkIndent >= 4) {
                        // closing fence should be indented less than 4 spaces
                        continue;
                    }

                    pos = state.skipChars(pos, marker);

                    // closing code fence must be at least as long as the opening one
                    if (pos - mem < len) {
                        continue;
                    }

                    // make sure tail has spaces only
                    pos = state.skipSpaces(pos);

                    if (pos < max) {
                        continue;
                    }

                    haveEndMarker = true;
                    // found!
                    break;
                }

                // If a fence has heading spaces, they should be removed from its inner block
                len = state.tShift[startLine];

                state.line = nextLine + (haveEndMarker ? 1 : 0);
                state.tokens.push({
                    type: 'fence',
                    params: params,
                    content: state.getLines(startLine + 1, nextLine, len, true),
                    lines: [startLine, state.line],
                    level: state.level
                });

                return true;
            };

        }, {}],
        23: [function (require, module, exports) {
// heading (#, ##, ...)

            'use strict';


            module.exports = function heading(state, startLine, endLine, silent) {
                var ch, level, tmp,
                    pos = state.bMarks[startLine] + state.tShift[startLine],
                    max = state.eMarks[startLine];

                if (pos >= max) {
                    return false;
                }

                ch = state.src.charCodeAt(pos);

                if (ch !== 0x23/* # */ || pos >= max) {
                    return false;
                }

                // count heading level
                level = 1;
                ch = state.src.charCodeAt(++pos);
                while (ch === 0x23/* # */ && pos < max && level <= 6) {
                    level++;
                    ch = state.src.charCodeAt(++pos);
                }

                if (level > 6 || (pos < max && ch !== 0x20/* space */)) {
                    return false;
                }

                if (silent) {
                    return true;
                }

                // Let's cut tails like '    ###  ' from the end of string

                max = state.skipCharsBack(max, 0x20, pos); // space
                tmp = state.skipCharsBack(max, 0x23, pos); // #
                if (tmp > pos && state.src.charCodeAt(tmp - 1) === 0x20/* space */) {
                    max = tmp;
                }

                state.line = startLine + 1;

                state.tokens.push({
                    type: 'heading_open',
                    hLevel: level,
                    lines: [startLine, state.line],
                    level: state.level
                });

                // only if header is not empty
                if (pos < max) {
                    state.tokens.push({
                        type: 'inline',
                        content: state.src.slice(pos, max).trim(),
                        level: state.level + 1,
                        lines: [startLine, state.line],
                        children: []
                    });
                }
                state.tokens.push({type: 'heading_close', hLevel: level, level: state.level});

                return true;
            };

        }, {}],
        24: [function (require, module, exports) {
// Horizontal rule

            'use strict';


            module.exports = function hr(state, startLine, endLine, silent) {
                var marker, cnt, ch,
                    pos = state.bMarks[startLine],
                    max = state.eMarks[startLine];

                pos += state.tShift[startLine];

                if (pos > max) {
                    return false;
                }

                marker = state.src.charCodeAt(pos++);

                // Check hr marker
                if (marker !== 0x2A/* * */ &&
                    marker !== 0x2D/* - */ &&
                    marker !== 0x5F/* _ */) {
                    return false;
                }

                // markers can be mixed with spaces, but there should be at least 3 one

                cnt = 1;
                while (pos < max) {
                    ch = state.src.charCodeAt(pos++);
                    if (ch !== marker && ch !== 0x20/* space */) {
                        return false;
                    }
                    if (ch === marker) {
                        cnt++;
                    }
                }

                if (cnt < 3) {
                    return false;
                }

                if (silent) {
                    return true;
                }

                state.line = startLine + 1;
                state.tokens.push({
                    type: 'hr',
                    lines: [startLine, state.line],
                    level: state.level
                });

                return true;
            };

        }, {}],
        25: [function (require, module, exports) {
// HTML block

            'use strict';


            var block_names = require('../common/html_blocks');


            var HTML_TAG_OPEN_RE = /^<([a-zA-Z]{1,15})[\s\/>]/;
            var HTML_TAG_CLOSE_RE = /^<\/([a-zA-Z]{1,15})[\s>]/;

            function isLetter(ch) {
                /*eslint no-bitwise:0*/
                var lc = ch | 0x20; // to lower case
                return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */);
            }

            module.exports = function html_block(state, startLine, endLine, silent) {
                var ch, match, nextLine,
                    pos = state.bMarks[startLine],
                    max = state.eMarks[startLine],
                    shift = state.tShift[startLine];

                pos += shift;

                if (!state.md.options.html) {
                    return false;
                }

                if (shift > 3 || pos + 2 >= max) {
                    return false;
                }

                if (state.src.charCodeAt(pos) !== 0x3C/* < */) {
                    return false;
                }

                ch = state.src.charCodeAt(pos + 1);

                if (ch === 0x21/* ! */ || ch === 0x3F/* ? */) {
                    // Directive start / comment start / processing instruction start
                    if (silent) {
                        return true;
                    }

                } else if (ch === 0x2F/* / */ || isLetter(ch)) {

                    // Probably start or end of tag
                    if (ch === 0x2F/* \ */) {
                        // closing tag
                        match = state.src.slice(pos, max).match(HTML_TAG_CLOSE_RE);
                        if (!match) {
                            return false;
                        }
                    } else {
                        // opening tag
                        match = state.src.slice(pos, max).match(HTML_TAG_OPEN_RE);
                        if (!match) {
                            return false;
                        }
                    }
                    // Make sure tag name is valid
                    if (block_names[match[1].toLowerCase()] !== true) {
                        return false;
                    }
                    if (silent) {
                        return true;
                    }

                } else {
                    return false;
                }

                // If we are here - we detected HTML block.
                // Let's roll down till empty line (block end).
                nextLine = startLine + 1;
                while (nextLine < state.lineMax && !state.isEmpty(nextLine)) {
                    nextLine++;
                }

                state.line = nextLine;
                state.tokens.push({
                    type: 'html_block',
                    level: state.level,
                    lines: [startLine, state.line],
                    content: state.getLines(startLine, nextLine, 0, true)
                });

                return true;
            };

        }, {"../common/html_blocks": 2}],
        26: [function (require, module, exports) {
// lheading (---, ===)

            'use strict';


            module.exports = function lheading(state, startLine, endLine/*, silent*/) {
                var marker, pos, max,
                    next = startLine + 1;

                if (next >= endLine) {
                    return false;
                }
                if (state.tShift[next] < state.blkIndent) {
                    return false;
                }

                // Scan next line

                if (state.tShift[next] - state.blkIndent > 3) {
                    return false;
                }

                pos = state.bMarks[next] + state.tShift[next];
                max = state.eMarks[next];

                if (pos >= max) {
                    return false;
                }

                marker = state.src.charCodeAt(pos);

                if (marker !== 0x2D/* - */ && marker !== 0x3D/* = */) {
                    return false;
                }

                pos = state.skipChars(pos, marker);

                pos = state.skipSpaces(pos);

                if (pos < max) {
                    return false;
                }

                pos = state.bMarks[startLine] + state.tShift[startLine];

                state.line = next + 1;
                state.tokens.push({
                    type: 'heading_open',
                    hLevel: marker === 0x3D/* = */ ? 1 : 2,
                    lines: [startLine, state.line],
                    level: state.level
                });
                state.tokens.push({
                    type: 'inline',
                    content: state.src.slice(pos, state.eMarks[startLine]).trim(),
                    level: state.level + 1,
                    lines: [startLine, state.line - 1],
                    children: []
                });
                state.tokens.push({
                    type: 'heading_close',
                    hLevel: marker === 0x3D/* = */ ? 1 : 2,
                    level: state.level
                });

                return true;
            };

        }, {}],
        27: [function (require, module, exports) {
// Lists

            'use strict';


// Search `[-+*][\n ]`, returns next pos arter marker on success
// or -1 on fail.
            function skipBulletListMarker(state, startLine) {
                var marker, pos, max;

                pos = state.bMarks[startLine] + state.tShift[startLine];
                max = state.eMarks[startLine];

                if (pos >= max) {
                    return -1;
                }

                marker = state.src.charCodeAt(pos++);
                // Check bullet
                if (marker !== 0x2A/* * */ &&
                    marker !== 0x2D/* - */ &&
                    marker !== 0x2B/* + */) {
                    return -1;
                }

                if (pos < max && state.src.charCodeAt(pos) !== 0x20) {
                    // " 1.test " - is not a list item
                    return -1;
                }

                return pos;
            }

// Search `\d+[.)][\n ]`, returns next pos arter marker on success
// or -1 on fail.
            function skipOrderedListMarker(state, startLine) {
                var ch,
                    pos = state.bMarks[startLine] + state.tShift[startLine],
                    max = state.eMarks[startLine];

                if (pos + 1 >= max) {
                    return -1;
                }

                ch = state.src.charCodeAt(pos++);

                if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) {
                    return -1;
                }

                for (; ;) {
                    // EOL -> fail
                    if (pos >= max) {
                        return -1;
                    }

                    ch = state.src.charCodeAt(pos++);

                    if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {
                        continue;
                    }

                    // found valid marker
                    if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {
                        break;
                    }

                    return -1;
                }


                if (pos < max && state.src.charCodeAt(pos) !== 0x20/* space */) {
                    // " 1.test " - is not a list item
                    return -1;
                }
                return pos;
            }

            function markTightParagraphs(state, idx) {
                var i, l,
                    level = state.level + 2;

                for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
                    if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
                        state.tokens[i + 2].tight = true;
                        state.tokens[i].tight = true;
                        i += 2;
                    }
                }
            }


            module.exports = function list(state, startLine, endLine, silent) {
                var nextLine,
                    indent,
                    oldTShift,
                    oldIndent,
                    oldTight,
                    oldParentType,
                    start,
                    posAfterMarker,
                    max,
                    indentAfterMarker,
                    markerValue,
                    markerCharCode,
                    isOrdered,
                    contentStart,
                    listTokIdx,
                    prevEmptyEnd,
                    listLines,
                    itemLines,
                    tight = true,
                    terminatorRules,
                    i, l, terminate;

                // Detect list type and position after marker
                if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
                    isOrdered = true;
                } else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {
                    isOrdered = false;
                } else {
                    return false;
                }

                // We should terminate list on style change. Remember first one to compare.
                markerCharCode = state.src.charCodeAt(posAfterMarker - 1);

                // For validation mode we can terminate immediately
                if (silent) {
                    return true;
                }

                // Start list
                listTokIdx = state.tokens.length;

                if (isOrdered) {
                    start = state.bMarks[startLine] + state.tShift[startLine];
                    markerValue = Number(state.src.substr(start, posAfterMarker - start - 1));

                    state.tokens.push({
                        type: 'ordered_list_open',
                        order: markerValue,
                        lines: listLines = [startLine, 0],
                        level: state.level++
                    });

                } else {
                    state.tokens.push({
                        type: 'bullet_list_open',
                        lines: listLines = [startLine, 0],
                        level: state.level++
                    });
                }

                //
                // Iterate list items
                //

                nextLine = startLine;
                prevEmptyEnd = false;
                terminatorRules = state.md.block.ruler.getRules('list');

                while (nextLine < endLine) {
                    contentStart = state.skipSpaces(posAfterMarker);
                    max = state.eMarks[nextLine];

                    if (contentStart >= max) {
                        // trimming space in "-    \n  3" case, indent is 1 here
                        indentAfterMarker = 1;
                    } else {
                        indentAfterMarker = contentStart - posAfterMarker;
                    }

                    // If we have more than 4 spaces, the indent is 1
                    // (the rest is just indented code block)
                    if (indentAfterMarker > 4) {
                        indentAfterMarker = 1;
                    }

                    // If indent is less than 1, assume that it's one, example:
                    //  "-\n  test"
                    if (indentAfterMarker < 1) {
                        indentAfterMarker = 1;
                    }

                    // "  -  test"
                    //  ^^^^^ - calculating total length of this thing
                    indent = (posAfterMarker - state.bMarks[nextLine]) + indentAfterMarker;

                    // Run subparser & write tokens
                    state.tokens.push({
                        type: 'list_item_open',
                        lines: itemLines = [startLine, 0],
                        level: state.level++
                    });

                    oldIndent = state.blkIndent;
                    oldTight = state.tight;
                    oldTShift = state.tShift[startLine];
                    oldParentType = state.parentType;
                    state.tShift[startLine] = contentStart - state.bMarks[startLine];
                    state.blkIndent = indent;
                    state.tight = true;
                    state.parentType = 'list';

                    state.md.block.tokenize(state, startLine, endLine, true);

                    // If any of list item is tight, mark list as tight
                    if (!state.tight || prevEmptyEnd) {
                        tight = false;
                    }
                    // Item become loose if finish with empty line,
                    // but we should filter last element, because it means list finish
                    prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1);

                    state.blkIndent = oldIndent;
                    state.tShift[startLine] = oldTShift;
                    state.tight = oldTight;
                    state.parentType = oldParentType;

                    state.tokens.push({
                        type: 'list_item_close',
                        level: --state.level
                    });

                    nextLine = startLine = state.line;
                    itemLines[1] = nextLine;
                    contentStart = state.bMarks[startLine];

                    if (nextLine >= endLine) {
                        break;
                    }

                    if (state.isEmpty(nextLine)) {
                        break;
                    }

                    //
                    // Try to check if list is terminated or continued.
                    //
                    if (state.tShift[nextLine] < state.blkIndent) {
                        break;
                    }

                    // fail if terminating block found
                    terminate = false;
                    for (i = 0, l = terminatorRules.length; i < l; i++) {
                        if (terminatorRules[i](state, nextLine, endLine, true)) {
                            terminate = true;
                            break;
                        }
                    }
                    if (terminate) {
                        break;
                    }

                    // fail if list has another type
                    if (isOrdered) {
                        posAfterMarker = skipOrderedListMarker(state, nextLine);
                        if (posAfterMarker < 0) {
                            break;
                        }
                    } else {
                        posAfterMarker = skipBulletListMarker(state, nextLine);
                        if (posAfterMarker < 0) {
                            break;
                        }
                    }

                    if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) {
                        break;
                    }
                }

                // Finilize list
                state.tokens.push({
                    type: isOrdered ? 'ordered_list_close' : 'bullet_list_close',
                    level: --state.level
                });
                listLines[1] = nextLine;

                state.line = nextLine;

                // mark paragraphs tight if needed
                if (tight) {
                    markTightParagraphs(state, listTokIdx);
                }

                return true;
            };

        }, {}],
        28: [function (require, module, exports) {
// Paragraph

            'use strict';


            module.exports = function paragraph(state, startLine/*, endLine*/) {
                var endLine, content, terminate, i, l,
                    nextLine = startLine + 1,
                    terminatorRules;

                endLine = state.lineMax;

                // jump line-by-line until empty one or EOF
                if (nextLine < endLine && !state.isEmpty(nextLine)) {
                    terminatorRules = state.md.block.ruler.getRules('paragraph');

                    for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
                        // this would be a code block normally, but after paragraph
                        // it's considered a lazy continuation regardless of what's there
                        if (state.tShift[nextLine] - state.blkIndent > 3) {
                            continue;
                        }

                        // Some tags can terminate paragraph without empty line.
                        terminate = false;
                        for (i = 0, l = terminatorRules.length; i < l; i++) {
                            if (terminatorRules[i](state, nextLine, endLine, true)) {
                                terminate = true;
                                break;
                            }
                        }
                        if (terminate) {
                            break;
                        }
                    }
                }

                content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();

                state.line = nextLine;
                if (content.length) {
                    state.tokens.push({
                        type: 'paragraph_open',
                        tight: false,
                        lines: [startLine, state.line],
                        level: state.level
                    });
                    state.tokens.push({
                        type: 'inline',
                        content: content,
                        level: state.level + 1,
                        lines: [startLine, state.line],
                        children: []
                    });
                    state.tokens.push({
                        type: 'paragraph_close',
                        tight: false,
                        level: state.level
                    });
                }

                return true;
            };

        }, {}],
        29: [function (require, module, exports) {
            'use strict';


            var parseLinkDestination = require('../helpers/parse_link_destination');
            var parseLinkTitle = require('../helpers/parse_link_title');
            var normalizeReference = require('../helpers/normalize_reference');


            module.exports = function reference(state, startLine, _endLine, silent) {
                var ch,
                    destEndPos,
                    destEndLineNo,
                    endLine,
                    href,
                    i,
                    l,
                    label,
                    labelEnd,
                    res,
                    start,
                    str,
                    terminate,
                    terminatorRules,
                    title,
                    lines = 0,
                    pos = state.bMarks[startLine] + state.tShift[startLine],
                    max = state.eMarks[startLine],
                    nextLine = startLine + 1;

                if (pos >= max) {
                    return false;
                }
                if (state.src.charCodeAt(pos) !== 0x5B/* [ */) {
                    return false;
                }

                endLine = state.lineMax;

                // jump line-by-line until empty one or EOF
                if (nextLine < endLine && !state.isEmpty(nextLine)) {
                    terminatorRules = state.md.block.ruler.getRules('references');

                    for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
                        // this would be a code block normally, but after paragraph
                        // it's considered a lazy continuation regardless of what's there
                        if (state.tShift[nextLine] - state.blkIndent > 3) {
                            continue;
                        }

                        // Some tags can terminate paragraph without empty line.
                        terminate = false;
                        for (i = 0, l = terminatorRules.length; i < l; i++) {
                            if (terminatorRules[i](state, nextLine, endLine, true)) {
                                terminate = true;
                                break;
                            }
                        }
                        if (terminate) {
                            break;
                        }
                    }
                }

                str = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
                max = str.length;

                for (pos = 1; pos < max; pos++) {
                    ch = str.charCodeAt(pos);
                    if (ch === 0x5B /* [ */) {
                        return false;
                    } else if (ch === 0x5D /* ] */) {
                        labelEnd = pos;
                        break;
                    } else if (ch === 0x0A /* \n */) {
                        lines++;
                    } else if (ch === 0x5C /* \ */) {
                        pos++;
                        if (pos < max && str.charCodeAt(pos) === 0x0A) {
                            lines++;
                        }
                    }
                }

                if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) {
                    return false;
                }

                // [label]:   destination   'title'
                //         ^^^ skip optional whitespace here
                for (pos = labelEnd + 2; pos < max; pos++) {
                    ch = str.charCodeAt(pos);
                    if (ch === 0x0A) {
                        lines++;
                    } else if (ch === 0x20) {
                        /*eslint no-empty:0*/
                    } else {
                        break;
                    }
                }

                // [label]:   destination   'title'
                //            ^^^^^^^^^^^ parse this
                res = parseLinkDestination(str, pos, max);
                if (!res.ok) {
                    return false;
                }
                if (!state.md.inline.validateLink(res.str)) {
                    return false;
                }
                href = res.str;
                pos = res.pos;
                lines += res.lines;

                // save cursor state, we could require to rollback later
                destEndPos = pos;
                destEndLineNo = lines;

                // [label]:   destination   'title'
                //                       ^^^ skipping those spaces
                start = pos;
                for (; pos < max; pos++) {
                    ch = str.charCodeAt(pos);
                    if (ch === 0x0A) {
                        lines++;
                    } else if (ch === 0x20) {
                        /*eslint no-empty:0*/
                    } else {
                        break;
                    }
                }

                // [label]:   destination   'title'
                //                          ^^^^^^^ parse this
                res = parseLinkTitle(str, pos, max);
                if (pos < max && start !== pos && res.ok) {
                    title = res.str;
                    pos = res.pos;
                    lines += res.lines;
                } else {
                    title = '';
                    pos = destEndPos;
                    lines = destEndLineNo;
                }

                // skip trailing spaces until the rest of the line
                while (pos < max && str.charCodeAt(pos) === 0x20/* space */) {
                    pos++;
                }

                if (pos < max && str.charCodeAt(pos) !== 0x0A) {
                    // garbage at the end of the line
                    return false;
                }

                if (silent) {
                    return true;
                }

                label = normalizeReference(str.slice(1, labelEnd));
                if (typeof state.env.references === 'undefined') {
                    state.env.references = {};
                }
                if (typeof state.env.references[label] === 'undefined') {
                    state.env.references[label] = {title: title, href: href};
                }

                state.line = startLine + lines + 1;
                return true;
            };

        }, {
            "../helpers/normalize_reference": 7,
            "../helpers/parse_link_destination": 8,
            "../helpers/parse_link_title": 10
        }],
        30: [function (require, module, exports) {
// Parser state class

            'use strict';


            function StateBlock(src, md, env, tokens) {
                var ch, s, start, pos, len, indent, indent_found;

                this.src = src;

                // link to parser instance
                this.md = md;

                this.env = env;

                //
                // Internal state vartiables
                //

                this.tokens = tokens;

                this.bMarks = [];  // line begin offsets for fast jumps
                this.eMarks = [];  // line end offsets for fast jumps
                this.tShift = [];  // indent for each line

                // block parser variables
                this.blkIndent = 0; // required block content indent
                                    // (for example, if we are in list)
                this.line = 0; // line index in src
                this.lineMax = 0; // lines count
                this.tight = false;  // loose/tight mode for lists
                this.parentType = 'root'; // if `list`, block parser stops on two newlines
                this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)

                this.level = 0;

                // renderer
                this.result = '';

                // Create caches
                // Generate markers.
                s = this.src;
                indent = 0;
                indent_found = false;

                for (start = pos = indent = 0, len = s.length; pos < len; pos++) {
                    ch = s.charCodeAt(pos);

                    if (!indent_found) {
                        if (ch === 0x20/* space */) {
                            indent++;
                            continue;
                        } else {
                            indent_found = true;
                        }
                    }

                    if (ch === 0x0A || pos === len - 1) {
                        if (ch !== 0x0A) {
                            pos++;
                        }
                        this.bMarks.push(start);
                        this.eMarks.push(pos);
                        this.tShift.push(indent);

                        indent_found = false;
                        indent = 0;
                        start = pos + 1;
                    }
                }

                // Push fake entry to simplify cache bounds checks
                this.bMarks.push(s.length);
                this.eMarks.push(s.length);
                this.tShift.push(0);

                this.lineMax = this.bMarks.length - 1; // don't count last fake line
            }

            StateBlock.prototype.isEmpty = function isEmpty(line) {
                return this.bMarks[line] + this.tShift[line] >= this.eMarks[line];
            };

            StateBlock.prototype.skipEmptyLines = function skipEmptyLines(from) {
                for (var max = this.lineMax; from < max; from++) {
                    if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {
                        break;
                    }
                }
                return from;
            };

// Skip spaces from given position.
            StateBlock.prototype.skipSpaces = function skipSpaces(pos) {
                for (var max = this.src.length; pos < max; pos++) {
                    if (this.src.charCodeAt(pos) !== 0x20/* space */) {
                        break;
                    }
                }
                return pos;
            };

// Skip char codes from given position
            StateBlock.prototype.skipChars = function skipChars(pos, code) {
                for (var max = this.src.length; pos < max; pos++) {
                    if (this.src.charCodeAt(pos) !== code) {
                        break;
                    }
                }
                return pos;
            };

// Skip char codes reverse from given position - 1
            StateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code, min) {
                if (pos <= min) {
                    return pos;
                }

                while (pos > min) {
                    if (code !== this.src.charCodeAt(--pos)) {
                        return pos + 1;
                    }
                }
                return pos;
            };

// cut lines range from source.
            StateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) {
                var i, first, last, queue, shift,
                    line = begin;

                if (begin >= end) {
                    return '';
                }

                // Opt: don't use push queue for single line;
                if (line + 1 === end) {
                    first = this.bMarks[line] + Math.min(this.tShift[line], indent);
                    last = keepLastLF ? this.bMarks[end] : this.eMarks[end - 1];
                    return this.src.slice(first, last);
                }

                queue = new Array(end - begin);

                for (i = 0; line < end; line++, i++) {
                    shift = this.tShift[line];
                    if (shift > indent) {
                        shift = indent;
                    }
                    if (shift < 0) {
                        shift = 0;
                    }

                    first = this.bMarks[line] + shift;

                    if (line + 1 < end || keepLastLF) {
                        // No need for bounds check because we have fake entry on tail.
                        last = this.eMarks[line] + 1;
                    } else {
                        last = this.eMarks[line];
                    }

                    queue[i] = this.src.slice(first, last);
                }

                return queue.join('');
            };


            module.exports = StateBlock;

        }, {}],
        31: [function (require, module, exports) {
// GFM table, non-standard

            'use strict';


            function getLine(state, line) {
                var pos = state.bMarks[line] + state.blkIndent,
                    max = state.eMarks[line];

                return state.src.substr(pos, max - pos);
            }


            module.exports = function table(state, startLine, endLine, silent) {
                var ch, lineText, pos, i, nextLine, rows,
                    aligns, t, tableLines, tbodyLines;

                // should have at least three lines
                if (startLine + 2 > endLine) {
                    return false;
                }

                nextLine = startLine + 1;

                if (state.tShift[nextLine] < state.blkIndent) {
                    return false;
                }

                // first character of the second line should be '|' or '-'

                pos = state.bMarks[nextLine] + state.tShift[nextLine];
                if (pos >= state.eMarks[nextLine]) {
                    return false;
                }

                ch = state.src.charCodeAt(pos);
                if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */) {
                    return false;
                }

                lineText = getLine(state, startLine + 1);
                if (!/^[-:| ]+$/.test(lineText)) {
                    return false;
                }

                rows = lineText.split('|');
                if (rows <= 2) {
                    return false;
                }
                aligns = [];
                for (i = 0; i < rows.length; i++) {
                    t = rows[i].trim();
                    if (!t) {
                        // allow empty columns before and after table, but not in between columns;
                        // e.g. allow ` |---| `, disallow ` ---||--- `
                        if (i === 0 || i === rows.length - 1) {
                            continue;
                        } else {
                            return false;
                        }
                    }

                    if (!/^:?-+:?$/.test(t)) {
                        return false;
                    }
                    if (t.charCodeAt(t.length - 1) === 0x3A/* : */) {
                        aligns.push(t.charCodeAt(0) === 0x3A/* : */ ? 'center' : 'right');
                    } else if (t.charCodeAt(0) === 0x3A/* : */) {
                        aligns.push('left');
                    } else {
                        aligns.push('');
                    }
                }

                lineText = getLine(state, startLine).trim();
                if (lineText.indexOf('|') === -1) {
                    return false;
                }
                rows = lineText.replace(/^\||\|$/g, '').split('|');
                if (aligns.length !== rows.length) {
                    return false;
                }
                if (silent) {
                    return true;
                }

                state.tokens.push({
                    type: 'table_open',
                    lines: tableLines = [startLine, 0],
                    level: state.level++
                });
                state.tokens.push({
                    type: 'thead_open',
                    lines: [startLine, startLine + 1],
                    level: state.level++
                });

                state.tokens.push({
                    type: 'tr_open',
                    lines: [startLine, startLine + 1],
                    level: state.level++
                });
                for (i = 0; i < rows.length; i++) {
                    state.tokens.push({
                        type: 'th_open',
                        align: aligns[i],
                        lines: [startLine, startLine + 1],
                        level: state.level++
                    });
                    state.tokens.push({
                        type: 'inline',
                        content: rows[i].trim(),
                        lines: [startLine, startLine + 1],
                        level: state.level,
                        children: []
                    });
                    state.tokens.push({type: 'th_close', level: --state.level});
                }
                state.tokens.push({type: 'tr_close', level: --state.level});
                state.tokens.push({type: 'thead_close', level: --state.level});

                state.tokens.push({
                    type: 'tbody_open',
                    lines: tbodyLines = [startLine + 2, 0],
                    level: state.level++
                });

                for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {
                    if (state.tShift[nextLine] < state.blkIndent) {
                        break;
                    }

                    lineText = getLine(state, nextLine).trim();
                    if (lineText.indexOf('|') === -1) {
                        break;
                    }
                    rows = lineText.replace(/^\||\|$/g, '').split('|');

                    state.tokens.push({type: 'tr_open', level: state.level++});
                    for (i = 0; i < rows.length; i++) {
                        state.tokens.push({type: 'td_open', align: aligns[i], level: state.level++});
                        state.tokens.push({
                            type: 'inline',
                            content: rows[i].replace(/^\|? *| *\|?$/g, ''),
                            level: state.level,
                            children: []
                        });
                        state.tokens.push({type: 'td_close', level: --state.level});
                    }
                    state.tokens.push({type: 'tr_close', level: --state.level});
                }
                state.tokens.push({type: 'tbody_close', level: --state.level});
                state.tokens.push({type: 'table_close', level: --state.level});

                tableLines[1] = tbodyLines[1] = nextLine;
                state.line = nextLine;
                return true;
            };

        }, {}],
        32: [function (require, module, exports) {
            'use strict';

            module.exports = function block(state) {

                if (state.inlineMode) {
                    state.tokens.push({
                        type: 'inline',
                        content: state.src,
                        level: 0,
                        lines: [0, 1],
                        children: []
                    });

                } else {
                    state.md.block.parse(state.src, state.md, state.env, state.tokens);
                }
            };

        }, {}],
        33: [function (require, module, exports) {
            'use strict';

            module.exports = function inline(state) {
                var tokens = state.tokens, tok, i, l;

                // Parse inlines
                for (i = 0, l = tokens.length; i < l; i++) {
                    tok = tokens[i];
                    if (tok.type === 'inline') {
                        state.md.inline.parse(tok.content, state.md, state.env, tok.children);
                    }
                }
            };

        }, {}],
        34: [function (require, module, exports) {
// Replace link-like texts with link nodes.
//
// Currently restricted by `inline.validateLink()` to http/https/ftp
//
            'use strict';


            var Autolinker = require('autolinker');
            var arrayReplaceAt = require('../common/utils').arrayReplaceAt;


            var LINK_SCAN_RE = /www|@|\:\/\//;


            function isLinkOpen(str) {
                return /^<a[>\s]/i.test(str);
            }

            function isLinkClose(str) {
                return /^<\/a\s*>/i.test(str);
            }

// Stupid fabric to avoid singletons, for thread safety.
// Required for engines like Nashorn.
//
            function createLinkifier() {
                var links = [];
                var autolinker = new Autolinker({
                    stripPrefix: false,
                    url: true,
                    email: true,
                    twitter: false,
                    replaceFn: function (autolinker, match) {
                        // Only collect matched strings but don't change anything.
                        switch (match.getType()) {
                            /*eslint default-case:0*/
                            case 'url':
                                links.push({
                                    text: match.matchedText,
                                    url: match.getUrl()
                                });
                                break;
                            case 'email':
                                links.push({
                                    text: match.matchedText,
                                    // normalize email protocol
                                    url: 'mailto:' + match.getEmail().replace(/^mailto:/i, '')
                                });
                                break;
                        }
                        return false;
                    }
                });

                return {
                    links: links,
                    autolinker: autolinker
                };
            }


            module.exports = function linkify(state) {
                var i, j, l, tokens, token, text, nodes, ln, pos, level, htmlLinkLevel,
                    blockTokens = state.tokens,
                    linkifier = null, links, autolinker;

                if (!state.md.options.linkify) {
                    return;
                }

                for (j = 0, l = blockTokens.length; j < l; j++) {
                    if (blockTokens[j].type !== 'inline') {
                        continue;
                    }
                    tokens = blockTokens[j].children;

                    htmlLinkLevel = 0;

                    // We scan from the end, to keep position when new tags added.
                    // Use reversed logic in links start/end match
                    for (i = tokens.length - 1; i >= 0; i--) {
                        token = tokens[i];

                        // Skip content of markdown links
                        if (token.type === 'link_close') {
                            i--;
                            while (tokens[i].level !== token.level && tokens[i].type !== 'link_open') {
                                i--;
                            }
                            continue;
                        }

                        // Skip content of html tag links
                        if (token.type === 'html_inline') {
                            if (isLinkOpen(token.content) && htmlLinkLevel > 0) {
                                htmlLinkLevel--;
                            }
                            if (isLinkClose(token.content)) {
                                htmlLinkLevel++;
                            }
                        }
                        if (htmlLinkLevel > 0) {
                            continue;
                        }

                        if (token.type === 'text' && LINK_SCAN_RE.test(token.content)) {

                            // Init linkifier in lazy manner, only if required.
                            if (!linkifier) {
                                linkifier = createLinkifier();
                                links = linkifier.links;
                                autolinker = linkifier.autolinker;
                            }

                            text = token.content;
                            links.length = 0;
                            autolinker.link(text);

                            if (!links.length) {
                                continue;
                            }

                            // Now split string to nodes
                            nodes = [];
                            level = token.level;

                            for (ln = 0; ln < links.length; ln++) {

                                if (!state.md.inline.validateLink(links[ln].url)) {
                                    continue;
                                }

                                pos = text.indexOf(links[ln].text);

                                if (pos) {
                                    level = level;
                                    nodes.push({
                                        type: 'text',
                                        content: text.slice(0, pos),
                                        level: level
                                    });
                                }
                                nodes.push({
                                    type: 'link_open',
                                    href: links[ln].url,
                                    target: '',
                                    title: '',
                                    level: level++
                                });
                                nodes.push({
                                    type: 'text',
                                    content: links[ln].text,
                                    level: level
                                });
                                nodes.push({
                                    type: 'link_close',
                                    level: --level
                                });
                                text = text.slice(pos + links[ln].text.length);
                            }
                            if (text.length) {
                                nodes.push({
                                    type: 'text',
                                    content: text,
                                    level: level
                                });
                            }

                            // replace current node
                            blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);
                        }
                    }
                }
            };

        }, {"../common/utils": 5, "autolinker": 51}],
        35: [function (require, module, exports) {
// Normalize input string

            'use strict';


            var TABS_SCAN_RE = /[\n\t]/g;
            var NEWLINES_RE = /\r[\n\u0085]|[\u2424\u2028\u0085]/g;
            var NULL_RE = /\u0000/g;


            module.exports = function inline(state) {
                var str, lineStart, lastTabPos;

                if (!state.normalizeInput) {
                    return;
                }

                // Normalize newlines
                str = state.src.replace(NEWLINES_RE, '\n');

                // Replace NULL characters
                str = str.replace(NULL_RE, '\uFFFD');

                // Replace tabs with proper number of spaces (1..4)
                if (str.indexOf('\t') >= 0) {
                    lineStart = 0;
                    lastTabPos = 0;

                    str = str.replace(TABS_SCAN_RE, function (match, offset) {
                        var result;
                        if (str.charCodeAt(offset) === 0x0A) {
                            lineStart = offset + 1;
                            lastTabPos = 0;
                            return match;
                        }
                        result = '    '.slice((offset - lineStart - lastTabPos) % 4);
                        lastTabPos = offset - lineStart + 1;
                        return result;
                    });
                }

                state.src = str;
            };

        }, {}],
        36: [function (require, module, exports) {
// Simple typographyc replacements
//
// '' → ‘’
// "" → “”. Set '«»' for Russian, '„“' for German, empty to disable
// (c) (C) → ©
// (tm) (TM) → ™
// (r) (R) → ®
// +- → ±
// (p) (P) -> §
// ... → … (also ?.... → ?.., !.... → !..)
// ???????? → ???, !!!!! → !!!, `,,` → `,`
// -- → &ndash;, --- → &mdash;
//
            'use strict';

// TODO:
// - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾
// - miltiplication 2 x 4 -> 2 × 4

            var RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/;

            var SCOPED_ABBR_RE = /\((c|tm|r|p)\)/ig;
            var SCOPED_ABBR = {
                'c': '©',
                'r': '®',
                'p': '§',
                'tm': '™'
            };

            function replaceScopedAbbr(str) {
                if (str.indexOf('(') < 0) {
                    return str;
                }

                return str.replace(SCOPED_ABBR_RE, function (match, name) {
                    return SCOPED_ABBR[name.toLowerCase()];
                });
            }


            module.exports = function replace(state) {
                var i, token, text, inlineTokens, blkIdx;

                if (!state.md.options.typographer) {
                    return;
                }

                for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {

                    if (state.tokens[blkIdx].type !== 'inline') {
                        continue;
                    }

                    inlineTokens = state.tokens[blkIdx].children;

                    for (i = inlineTokens.length - 1; i >= 0; i--) {
                        token = inlineTokens[i];
                        if (token.type === 'text') {
                            text = token.content;

                            text = replaceScopedAbbr(text);

                            if (RARE_RE.test(text)) {
                                text = text.replace(/\+-/g, '±')
                                    // .., ..., ....... -> …
                                    // but ?..... & !..... -> ?.. & !..
                                    .replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..')
                                    .replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',')
                                    // em-dash
                                    .replace(/(^|[^-])---([^-]|$)/mg, '$1\u2014$2')
                                    // en-dash
                                    .replace(/(^|\s)--(\s|$)/mg, '$1\u2013$2')
                                    .replace(/(^|[^-\s])--([^-\s]|$)/mg, '$1\u2013$2');
                            }

                            token.content = text;
                        }
                    }
                }
            };

        }, {}],
        37: [function (require, module, exports) {
// Convert straight quotation marks to typographic ones
//
            'use strict';


            var QUOTE_TEST_RE = /['"]/;
            var QUOTE_RE = /['"]/g;
            var PUNCT_RE = /[-\s()\[\]]/;
            var APOSTROPHE = '\u2019';
            /* ’ */

// This function returns true if the character at `pos`
// could be inside a word.
            function isLetter(str, pos) {
                if (pos < 0 || pos >= str.length) {
                    return false;
                }
                return !PUNCT_RE.test(str[pos]);
            }


            function replaceAt(str, index, ch) {
                return str.substr(0, index) + ch + str.substr(index + 1);
            }


            module.exports = function smartquotes(state) {
                /*eslint max-depth:0*/
                var i, token, text, t, pos, max, thisLevel, lastSpace, nextSpace, item,
                    canOpen, canClose, j, isSingle, blkIdx, tokens,
                    stack;

                if (!state.md.options.typographer) {
                    return;
                }

                stack = [];

                for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {

                    if (state.tokens[blkIdx].type !== 'inline') {
                        continue;
                    }

                    tokens = state.tokens[blkIdx].children;
                    stack.length = 0;

                    for (i = 0; i < tokens.length; i++) {
                        token = tokens[i];

                        if (token.type !== 'text' || QUOTE_TEST_RE.test(token.text)) {
                            continue;
                        }

                        thisLevel = tokens[i].level;

                        for (j = stack.length - 1; j >= 0; j--) {
                            if (stack[j].level <= thisLevel) {
                                break;
                            }
                        }
                        stack.length = j + 1;

                        text = token.content;
                        pos = 0;
                        max = text.length;

                        /*eslint no-labels:0,block-scoped-var:0*/
                        OUTER:
                            while (pos < max) {
                                QUOTE_RE.lastIndex = pos;
                                t = QUOTE_RE.exec(text);
                                if (!t) {
                                    break;
                                }

                                lastSpace = !isLetter(text, t.index - 1);
                                pos = t.index + 1;
                                isSingle = (t[0] === "'");
                                nextSpace = !isLetter(text, pos);

                                if (!nextSpace && !lastSpace) {
                                    // middle of word
                                    if (isSingle) {
                                        token.content = replaceAt(token.content, t.index, APOSTROPHE);
                                    }
                                    continue;
                                }

                                canOpen = !nextSpace;
                                canClose = !lastSpace;

                                if (canClose) {
                                    // this could be a closing quote, rewind the stack to get a match
                                    for (j = stack.length - 1; j >= 0; j--) {
                                        item = stack[j];
                                        if (stack[j].level < thisLevel) {
                                            break;
                                        }
                                        if (item.single === isSingle && stack[j].level === thisLevel) {
                                            item = stack[j];
                                            if (isSingle) {
                                                tokens[item.token].content = replaceAt(
                                                    tokens[item.token].content, item.pos, state.md.options.quotes[2]);
                                                token.content = replaceAt(
                                                    token.content, t.index, state.md.options.quotes[3]);
                                            } else {
                                                tokens[item.token].content = replaceAt(
                                                    tokens[item.token].content, item.pos, state.md.options.quotes[0]);
                                                token.content = replaceAt(token.content, t.index, state.md.options.quotes[1]);
                                            }
                                            stack.length = j;
                                            continue OUTER;
                                        }
                                    }
                                }

                                if (canOpen) {
                                    stack.push({
                                        token: i,
                                        pos: t.index,
                                        single: isSingle,
                                        level: thisLevel
                                    });
                                } else if (canClose && isSingle) {
                                    token.content = replaceAt(token.content, t.index, APOSTROPHE);
                                }
                            }
                    }
                }
            };

        }, {}],
        38: [function (require, module, exports) {
// Core state object
//
            'use strict';

            module.exports = function StateCore(src, md, env) {
                this.src = src;
                this.env = env;
                this.tokens = [];
                this.inlineMode = false;
                this.normalizeInput = true;
                this.md = md; // link to parser instance
            };

        }, {}],
        39: [function (require, module, exports) {
// Process autolinks '<protocol:...>'

            'use strict';

            var url_schemas = require('../common/url_schemas');
            var normalizeLink = require('../common/utils').normalizeLink;


            /*eslint max-len:0*/
            var EMAIL_RE = /^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/;
            var AUTOLINK_RE = /^<([a-zA-Z.\-]{1,25}):([^<>\x00-\x20]*)>/;


            module.exports = function autolink(state, silent) {
                var tail, linkMatch, emailMatch, url, fullUrl, pos = state.pos;

                if (state.src.charCodeAt(pos) !== 0x3C/* < */) {
                    return false;
                }

                tail = state.src.slice(pos);

                if (tail.indexOf('>') < 0) {
                    return false;
                }

                linkMatch = tail.match(AUTOLINK_RE);

                if (linkMatch) {
                    if (url_schemas.indexOf(linkMatch[1].toLowerCase()) < 0) {
                        return false;
                    }

                    url = linkMatch[0].slice(1, -1);
                    fullUrl = normalizeLink(url);
                    if (!state.md.inline.validateLink(url)) {
                        return false;
                    }

                    if (!silent) {
                        state.push({
                            type: 'link_open',
                            href: fullUrl,
                            target: '',
                            level: state.level
                        });
                        state.push({
                            type: 'text',
                            content: url,
                            level: state.level + 1
                        });
                        state.push({type: 'link_close', level: state.level});
                    }

                    state.pos += linkMatch[0].length;
                    return true;
                }

                emailMatch = tail.match(EMAIL_RE);

                if (emailMatch) {

                    url = emailMatch[0].slice(1, -1);

                    fullUrl = normalizeLink('mailto:' + url);
                    if (!state.md.inline.validateLink(fullUrl)) {
                        return false;
                    }

                    if (!silent) {
                        state.push({
                            type: 'link_open',
                            href: fullUrl,
                            target: '',
                            level: state.level
                        });
                        state.push({
                            type: 'text',
                            content: url,
                            level: state.level + 1
                        });
                        state.push({type: 'link_close', level: state.level});
                    }

                    state.pos += emailMatch[0].length;
                    return true;
                }

                return false;
            };

        }, {"../common/url_schemas": 4, "../common/utils": 5}],
        40: [function (require, module, exports) {
// Parse backticks

            'use strict';

            module.exports = function backtick(state, silent) {
                var start, max, marker, matchStart, matchEnd,
                    pos = state.pos,
                    ch = state.src.charCodeAt(pos);

                if (ch !== 0x60/* ` */) {
                    return false;
                }

                start = pos;
                pos++;
                max = state.posMax;

                while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) {
                    pos++;
                }

                marker = state.src.slice(start, pos);

                matchStart = matchEnd = pos;

                while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {
                    matchEnd = matchStart + 1;

                    while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) {
                        matchEnd++;
                    }

                    if (matchEnd - matchStart === marker.length) {
                        if (!silent) {
                            state.push({
                                type: 'code_inline',
                                content: state.src.slice(pos, matchStart)
                                    .replace(/[ \n]+/g, ' ')
                                    .trim(),
                                level: state.level
                            });
                        }
                        state.pos = matchEnd;
                        return true;
                    }
                }

                if (!silent) {
                    state.pending += marker;
                }
                state.pos += marker.length;
                return true;
            };

        }, {}],
        41: [function (require, module, exports) {
// Process *this* and _that_

            'use strict';

            var isWhiteSpace = require('../common/utils').isWhiteSpace;
            var isPunctChar = require('../common/utils').isPunctChar;
            var isMdAsciiPunct = require('../common/utils').isMdAsciiPunct;


            function isAlphaNum(code) {
                return (code >= 0x30 /* 0 */ && code <= 0x39 /* 9 */) ||
                    (code >= 0x41 /* A */ && code <= 0x5A /* Z */) ||
                    (code >= 0x61 /* a */ && code <= 0x7A /* z */);
            }

// parse sequence of emphasis markers,
// "start" should point at a valid marker
            function scanDelims(state, start) {
                var pos = start, lastChar, nextChar, count,
                    isLastWhiteSpace, isLastPunctChar,
                    isNextWhiteSpace, isNextPunctChar,
                    can_open = true,
                    can_close = true,
                    max = state.posMax,
                    marker = state.src.charCodeAt(start);

                lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1;

                while (pos < max && state.src.charCodeAt(pos) === marker) {
                    pos++;
                }
                if (pos >= max) {
                    can_open = false;
                }
                count = pos - start;

                nextChar = pos < max ? state.src.charCodeAt(pos) : -1;

                isLastPunctChar = lastChar >= 0 &&
                    (isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar)));
                isNextPunctChar = nextChar >= 0 &&
                    (isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar)));
                isLastWhiteSpace = lastChar >= 0 && isWhiteSpace(lastChar);
                isNextWhiteSpace = nextChar >= 0 && isWhiteSpace(nextChar);

                if (isNextWhiteSpace) {
                    can_open = false;
                } else if (isNextPunctChar) {
                    if (!(isLastWhiteSpace || isLastPunctChar || lastChar === -1)) {
                        can_open = false;
                    }
                }

                if (isLastWhiteSpace) {
                    can_close = false;
                } else if (isLastPunctChar) {
                    if (!(isNextWhiteSpace || isNextPunctChar || nextChar === -1)) {
                        can_close = false;
                    }
                }

                if (marker === 0x5F /* _ */) {
                    // check if we aren't inside the word
                    if (isAlphaNum(lastChar)) {
                        can_open = false;
                    }
                    if (isAlphaNum(nextChar)) {
                        can_close = false;
                    }
                }

                return {
                    can_open: can_open,
                    can_close: can_close,
                    delims: count
                };
            }

            module.exports = function emphasis(state, silent) {
                var startCount,
                    count,
                    found,
                    oldCount,
                    newCount,
                    stack,
                    res,
                    max = state.posMax,
                    start = state.pos,
                    marker = state.src.charCodeAt(start);

                if (marker !== 0x5F/* _ */ && marker !== 0x2A /* * */) {
                    return false;
                }
                if (silent) {
                    return false;
                } // don't run any pairs in validation mode

                res = scanDelims(state, start);
                startCount = res.delims;
                if (!res.can_open) {
                    state.pos += startCount;
                    // Earlier we checked !silent, but this implementation does not need it
                    state.pending += state.src.slice(start, state.pos);
                    return true;
                }

                state.pos = start + startCount;
                stack = [startCount];

                while (state.pos < max) {
                    if (state.src.charCodeAt(state.pos) === marker) {
                        res = scanDelims(state, state.pos);
                        count = res.delims;
                        if (res.can_close) {
                            oldCount = stack.pop();
                            newCount = count;

                            while (oldCount !== newCount) {
                                if (newCount < oldCount) {
                                    stack.push(oldCount - newCount);
                                    break;
                                }

                                // assert(newCount > oldCount)
                                newCount -= oldCount;

                                if (stack.length === 0) {
                                    break;
                                }
                                state.pos += oldCount;
                                oldCount = stack.pop();
                            }

                            if (stack.length === 0) {
                                startCount = oldCount;
                                found = true;
                                break;
                            }
                            state.pos += count;
                            continue;
                        }

                        if (res.can_open) {
                            stack.push(count);
                        }
                        state.pos += count;
                        continue;
                    }

                    state.md.inline.skipToken(state);
                }

                if (!found) {
                    // parser failed to find ending tag, so it's not valid emphasis
                    state.pos = start;
                    return false;
                }

                // found!
                state.posMax = state.pos;
                state.pos = start + startCount;

                // Earlier we checked !silent, but this implementation does not need it

                // we have `startCount` starting and ending markers,
                // now trying to serialize them into tokens
                for (count = startCount; count > 1; count -= 2) {
                    state.push({type: 'strong_open', level: state.level++});
                }
                if (count % 2) {
                    state.push({type: 'em_open', level: state.level++});
                }

                state.md.inline.tokenize(state);

                if (count % 2) {
                    state.push({type: 'em_close', level: --state.level});
                }
                for (count = startCount; count > 1; count -= 2) {
                    state.push({type: 'strong_close', level: --state.level});
                }

                state.pos = state.posMax + startCount;
                state.posMax = max;
                return true;
            };

        }, {"../common/utils": 5}],
        42: [function (require, module, exports) {
// Process html entity - &#123;, &#xAF;, &quot;, ...

            'use strict';

            var entities = require('../common/entities');
            var has = require('../common/utils').has;
            var isValidEntityCode = require('../common/utils').isValidEntityCode;
            var fromCodePoint = require('../common/utils').fromCodePoint;


            var DIGITAL_RE = /^&#((?:x[a-f0-9]{1,8}|[0-9]{1,8}));/i;
            var NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;


            module.exports = function entity(state, silent) {
                var ch, code, match, pos = state.pos, max = state.posMax;

                if (state.src.charCodeAt(pos) !== 0x26/* & */) {
                    return false;
                }

                if (pos + 1 < max) {
                    ch = state.src.charCodeAt(pos + 1);

                    if (ch === 0x23 /* # */) {
                        match = state.src.slice(pos).match(DIGITAL_RE);
                        if (match) {
                            if (!silent) {
                                code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);
                                state.pending += isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);
                            }
                            state.pos += match[0].length;
                            return true;
                        }
                    } else {
                        match = state.src.slice(pos).match(NAMED_RE);
                        if (match) {
                            if (has(entities, match[1])) {
                                if (!silent) {
                                    state.pending += entities[match[1]];
                                }
                                state.pos += match[0].length;
                                return true;
                            }
                        }
                    }
                }

                if (!silent) {
                    state.pending += '&';
                }
                state.pos++;
                return true;
            };

        }, {"../common/entities": 1, "../common/utils": 5}],
        43: [function (require, module, exports) {
// Proceess escaped chars and hardbreaks

            'use strict';

            var ESCAPED = [];

            for (var i = 0; i < 256; i++) {
                ESCAPED.push(0);
            }

            '\\!"#$%&\'()*+,./:;<=>?@[]^_`{|}~-'
                .split('').forEach(function (ch) {
                ESCAPED[ch.charCodeAt(0)] = 1;
            });


            module.exports = function escape(state, silent) {
                var ch, pos = state.pos, max = state.posMax;

                if (state.src.charCodeAt(pos) !== 0x5C/* \ */) {
                    return false;
                }

                pos++;

                if (pos < max) {
                    ch = state.src.charCodeAt(pos);

                    if (ch < 256 && ESCAPED[ch] !== 0) {
                        if (!silent) {
                            state.pending += state.src[pos];
                        }
                        state.pos += 2;
                        return true;
                    }

                    if (ch === 0x0A) {
                        if (!silent) {
                            state.push({
                                type: 'hardbreak',
                                level: state.level
                            });
                        }

                        pos++;
                        // skip leading whitespaces from next line
                        while (pos < max && state.src.charCodeAt(pos) === 0x20) {
                            pos++;
                        }

                        state.pos = pos;
                        return true;
                    }
                }

                if (!silent) {
                    state.pending += '\\';
                }
                state.pos++;
                return true;
            };

        }, {}],
        44: [function (require, module, exports) {
// Process html tags

            'use strict';


            var HTML_TAG_RE = require('../common/html_re').HTML_TAG_RE;

            var COMMENT_RE = /^<!--[\s\S]*?-->$/;

            function isLetter(ch) {
                /*eslint no-bitwise:0*/
                var lc = ch | 0x20; // to lower case
                return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */);
            }


            module.exports = function html_inline(state, silent) {
                var ch, match, max, content, pos = state.pos;

                if (!state.md.options.html) {
                    return false;
                }

                // Check start
                max = state.posMax;
                if (state.src.charCodeAt(pos) !== 0x3C/* < */ ||
                    pos + 2 >= max) {
                    return false;
                }

                // Quick fail on second char
                ch = state.src.charCodeAt(pos + 1);
                if (ch !== 0x21/* ! */ &&
                    ch !== 0x3F/* ? */ &&
                    ch !== 0x2F/* / */ && !isLetter(ch)) {
                    return false;
                }

                match = state.src.slice(pos).match(HTML_TAG_RE);
                if (!match) {
                    return false;
                }

                content = state.src.slice(pos, pos + match[0].length);

                // Additional check for comments
                if (COMMENT_RE.test(content)) {
                    if (/(^>|^->|--|-$)/.test(content.slice(4, -3))) {
                        return false;
                    }
                }

                if (!silent) {
                    state.push({
                        type: 'html_inline',
                        content: content,
                        level: state.level
                    });
                }
                state.pos += match[0].length;
                return true;
            };

        }, {"../common/html_re": 3}],
        45: [function (require, module, exports) {
// Process ![image](<src> "title")

            'use strict';

            var parseLinkLabel = require('../helpers/parse_link_label');
            var parseLinkDestination = require('../helpers/parse_link_destination');
            var parseLinkTitle = require('../helpers/parse_link_title');
            var normalizeReference = require('../helpers/normalize_reference');


            module.exports = function image(state, silent) {
                var code,
                    href,
                    label,
                    labelEnd,
                    labelStart,
                    pos,
                    ref,
                    res,
                    title,
                    tokens,
                    start,
                    oldPos = state.pos,
                    max = state.posMax;

                if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) {
                    return false;
                }
                if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) {
                    return false;
                }

                labelStart = state.pos + 2;
                labelEnd = parseLinkLabel(state, state.pos + 1, false);

                // parser failed to find ']', so it's not a valid link
                if (labelEnd < 0) {
                    return false;
                }

                pos = labelEnd + 1;
                if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {
                    //
                    // Inline link
                    //

                    // [link](  <href>  "title"  )
                    //        ^^ skipping these spaces
                    pos++;
                    for (; pos < max; pos++) {
                        code = state.src.charCodeAt(pos);
                        if (code !== 0x20 && code !== 0x0A) {
                            break;
                        }
                    }
                    if (pos >= max) {
                        return false;
                    }

                    // [link](  <href>  "title"  )
                    //          ^^^^^^ parsing link destination
                    start = pos;
                    res = parseLinkDestination(state.src, pos, state.posMax);
                    if (res.ok && state.md.inline.validateLink(res.str)) {
                        href = res.str;
                        pos = res.pos;
                    } else {
                        href = '';
                    }

                    // [link](  <href>  "title"  )
                    //                ^^ skipping these spaces
                    start = pos;
                    for (; pos < max; pos++) {
                        code = state.src.charCodeAt(pos);
                        if (code !== 0x20 && code !== 0x0A) {
                            break;
                        }
                    }

                    // [link](  <href>  "title"  )
                    //                  ^^^^^^^ parsing link title
                    res = parseLinkTitle(state.src, pos, state.posMax);
                    if (pos < max && start !== pos && res.ok) {
                        title = res.str;
                        pos = res.pos;

                        // [link](  <href>  "title"  )
                        //                         ^^ skipping these spaces
                        for (; pos < max; pos++) {
                            code = state.src.charCodeAt(pos);
                            if (code !== 0x20 && code !== 0x0A) {
                                break;
                            }
                        }
                    } else {
                        title = '';
                    }

                    if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {
                        state.pos = oldPos;
                        return false;
                    }
                    pos++;
                } else {
                    //
                    // Link reference
                    //
                    if (typeof state.env.references === 'undefined') {
                        return false;
                    }

                    // [foo]  [bar]
                    //      ^^ optional whitespace (can include newlines)
                    for (; pos < max; pos++) {
                        code = state.src.charCodeAt(pos);
                        if (code !== 0x20 && code !== 0x0A) {
                            break;
                        }
                    }

                    if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {
                        start = pos + 1;
                        pos = parseLinkLabel(state, pos);
                        if (pos >= 0) {
                            label = state.src.slice(start, pos++);
                        } else {
                            pos = labelEnd + 1;
                        }
                    } else {
                        pos = labelEnd + 1;
                    }

                    // covers label === '' and label === undefined
                    // (collapsed reference link and shortcut reference link respectively)
                    if (!label) {
                        label = state.src.slice(labelStart, labelEnd);
                    }

                    ref = state.env.references[normalizeReference(label)];
                    if (!ref) {
                        state.pos = oldPos;
                        return false;
                    }
                    href = ref.href;
                    title = ref.title;
                }

                //
                // We found the end of the link, and know for a fact it's a valid link;
                // so all that's left to do is to call tokenizer.
                //
                if (!silent) {
                    state.pos = labelStart;
                    state.posMax = labelEnd;

                    var newState = new state.md.inline.State(
                        state.src.slice(labelStart, labelEnd),
                        state.md,
                        state.env,
                        tokens = []
                    );
                    newState.md.inline.tokenize(newState);

                    state.push({
                        type: 'image',
                        src: href,
                        title: title,
                        tokens: tokens,
                        level: state.level
                    });
                }

                state.pos = pos;
                state.posMax = max;
                return true;
            };

        }, {
            "../helpers/normalize_reference": 7,
            "../helpers/parse_link_destination": 8,
            "../helpers/parse_link_label": 9,
            "../helpers/parse_link_title": 10
        }],
        46: [function (require, module, exports) {
// Process [link](<to> "stuff")

            'use strict';

            var parseLinkLabel = require('../helpers/parse_link_label');
            var parseLinkDestination = require('../helpers/parse_link_destination');
            var parseLinkTitle = require('../helpers/parse_link_title');
            var normalizeReference = require('../helpers/normalize_reference');


            module.exports = function link(state, silent) {
                var code,
                    href,
                    label,
                    labelEnd,
                    labelStart,
                    pos,
                    res,
                    ref,
                    title,
                    oldPos = state.pos,
                    max = state.posMax,
                    start = state.pos;

                if (state.src.charCodeAt(state.pos) !== 0x5B/* [ */) {
                    return false;
                }

                labelStart = state.pos + 1;
                labelEnd = parseLinkLabel(state, state.pos, true);

                // parser failed to find ']', so it's not a valid link
                if (labelEnd < 0) {
                    return false;
                }

                pos = labelEnd + 1;
                if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {
                    //
                    // Inline link
                    //

                    // [link](  <href>  "title"  )
                    //        ^^ skipping these spaces
                    pos++;
                    for (; pos < max; pos++) {
                        code = state.src.charCodeAt(pos);
                        if (code !== 0x20 && code !== 0x0A) {
                            break;
                        }
                    }
                    if (pos >= max) {
                        return false;
                    }

                    // [link](  <href>  "title"  )
                    //          ^^^^^^ parsing link destination
                    start = pos;
                    res = parseLinkDestination(state.src, pos, state.posMax);
                    if (res.ok && state.md.inline.validateLink(res.str)) {
                        href = res.str;
                        pos = res.pos;
                    } else {
                        href = '';
                    }

                    // [link](  <href>  "title"  )
                    //                ^^ skipping these spaces
                    start = pos;
                    for (; pos < max; pos++) {
                        code = state.src.charCodeAt(pos);
                        if (code !== 0x20 && code !== 0x0A) {
                            break;
                        }
                    }

                    // [link](  <href>  "title"  )
                    //                  ^^^^^^^ parsing link title
                    res = parseLinkTitle(state.src, pos, state.posMax);
                    if (pos < max && start !== pos && res.ok) {
                        title = res.str;
                        pos = res.pos;

                        // [link](  <href>  "title"  )
                        //                         ^^ skipping these spaces
                        for (; pos < max; pos++) {
                            code = state.src.charCodeAt(pos);
                            if (code !== 0x20 && code !== 0x0A) {
                                break;
                            }
                        }
                    } else {
                        title = '';
                    }

                    if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {
                        state.pos = oldPos;
                        return false;
                    }
                    pos++;
                } else {
                    //
                    // Link reference
                    //
                    if (typeof state.env.references === 'undefined') {
                        return false;
                    }

                    // [foo]  [bar]
                    //      ^^ optional whitespace (can include newlines)
                    for (; pos < max; pos++) {
                        code = state.src.charCodeAt(pos);
                        if (code !== 0x20 && code !== 0x0A) {
                            break;
                        }
                    }

                    if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {
                        start = pos + 1;
                        pos = parseLinkLabel(state, pos);
                        if (pos >= 0) {
                            label = state.src.slice(start, pos++);
                        } else {
                            pos = labelEnd + 1;
                        }
                    } else {
                        pos = labelEnd + 1;
                    }

                    // covers label === '' and label === undefined
                    // (collapsed reference link and shortcut reference link respectively)
                    if (!label) {
                        label = state.src.slice(labelStart, labelEnd);
                    }

                    ref = state.env.references[normalizeReference(label)];
                    if (!ref) {
                        state.pos = oldPos;
                        return false;
                    }
                    href = ref.href;
                    title = ref.title;
                }

                //
                // We found the end of the link, and know for a fact it's a valid link;
                // so all that's left to do is to call tokenizer.
                //
                if (!silent) {
                    state.pos = labelStart;
                    state.posMax = labelEnd;

                    state.push({
                        type: 'link_open',
                        href: href,
                        target: '',
                        title: title,
                        level: state.level++
                    });
                    state.md.inline.tokenize(state);
                    state.push({type: 'link_close', level: --state.level});
                }

                state.pos = pos;
                state.posMax = max;
                return true;
            };

        }, {
            "../helpers/normalize_reference": 7,
            "../helpers/parse_link_destination": 8,
            "../helpers/parse_link_label": 9,
            "../helpers/parse_link_title": 10
        }],
        47: [function (require, module, exports) {
// Proceess '\n'

            'use strict';

            module.exports = function newline(state, silent) {
                var pmax, max, pos = state.pos;

                if (state.src.charCodeAt(pos) !== 0x0A/* \n */) {
                    return false;
                }

                pmax = state.pending.length - 1;
                max = state.posMax;

                // '  \n' -> hardbreak
                // Lookup in pending chars is bad practice! Don't copy to other rules!
                // Pending string is stored in concat mode, indexed lookups will cause
                // convertion to flat mode.
                if (!silent) {
                    if (pmax >= 0 && state.pending.charCodeAt(pmax) === 0x20) {
                        if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 0x20) {
                            state.pending = state.pending.replace(/ +$/, '');
                            state.push({
                                type: 'hardbreak',
                                level: state.level
                            });
                        } else {
                            state.pending = state.pending.slice(0, -1);
                            state.push({
                                type: 'softbreak',
                                level: state.level
                            });
                        }

                    } else {
                        state.push({
                            type: 'softbreak',
                            level: state.level
                        });
                    }
                }

                pos++;

                // skip heading spaces for next line
                while (pos < max && state.src.charCodeAt(pos) === 0x20) {
                    pos++;
                }

                state.pos = pos;
                return true;
            };

        }, {}],
        48: [function (require, module, exports) {
// Inline parser state

            'use strict';


            function StateInline(src, md, env, outTokens) {
                this.src = src;
                this.env = env;
                this.md = md;
                this.tokens = outTokens;

                this.pos = 0;
                this.posMax = this.src.length;
                this.level = 0;
                this.pending = '';
                this.pendingLevel = 0;

                this.cache = [];        // Stores { start: end } pairs. Useful for backtrack
                                        // optimization of pairs parse (emphasis, strikes).

                // Link parser state vars

                this.labelUnmatchedScopes = 0; // Track unpaired `[` for link labels
                                               // (backtrack optimization)
            }


// Flush pending text
//
            StateInline.prototype.pushPending = function () {
                this.tokens.push({
                    type: 'text',
                    content: this.pending,
                    level: this.pendingLevel
                });
                this.pending = '';
            };


// Push new token to "stream".
// If pending text exists - flush it as text token
//
            StateInline.prototype.push = function (token) {
                if (this.pending) {
                    this.pushPending();
                }

                this.tokens.push(token);
                this.pendingLevel = this.level;
            };


// Store value to cache.
// !!! Implementation has parser-specific optimizations
// !!! keys MUST be integer, >= 0; values MUST be integer, > 0
//
            StateInline.prototype.cacheSet = function (key, val) {
                for (var i = this.cache.length; i <= key; i++) {
                    this.cache.push(0);
                }

                this.cache[key] = val;
            };


// Get cache value
//
            StateInline.prototype.cacheGet = function (key) {
                return key < this.cache.length ? this.cache[key] : 0;
            };


            module.exports = StateInline;

        }, {}],
        49: [function (require, module, exports) {
            'use strict';


// parse sequence of markers,
// "start" should point at a valid marker
            function scanDelims(state, start) {
                var pos = start, lastChar, nextChar, count,
                    can_open = true,
                    can_close = true,
                    max = state.posMax,
                    marker = state.src.charCodeAt(start);

                lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1;

                while (pos < max && state.src.charCodeAt(pos) === marker) {
                    pos++;
                }
                if (pos >= max) {
                    can_open = false;
                }
                count = pos - start;

                nextChar = pos < max ? state.src.charCodeAt(pos) : -1;

                // check whitespace conditions
                if (nextChar === 0x20 || nextChar === 0x0A) {
                    can_open = false;
                }
                if (lastChar === 0x20 || lastChar === 0x0A) {
                    can_close = false;
                }

                return {
                    can_open: can_open,
                    can_close: can_close,
                    delims: count
                };
            }


            module.exports = function strikethrough(state, silent) {
                var startCount,
                    count,
                    tagCount,
                    found,
                    stack,
                    res,
                    max = state.posMax,
                    start = state.pos,
                    marker = state.src.charCodeAt(start);

                if (marker !== 0x7E/* ~ */) {
                    return false;
                }
                if (silent) {
                    return false;
                } // don't run any pairs in validation mode

                res = scanDelims(state, start);
                startCount = res.delims;
                if (!res.can_open) {
                    state.pos += startCount;
                    // Earlier we checked !silent, but this implementation does not need it
                    state.pending += state.src.slice(start, state.pos);
                    return true;
                }

                stack = Math.floor(startCount / 2);
                if (stack <= 0) {
                    return false;
                }
                state.pos = start + startCount;

                while (state.pos < max) {
                    if (state.src.charCodeAt(state.pos) === marker) {
                        res = scanDelims(state, state.pos);
                        count = res.delims;
                        tagCount = Math.floor(count / 2);
                        if (res.can_close) {
                            if (tagCount >= stack) {
                                state.pos += count - 2;
                                found = true;
                                break;
                            }
                            stack -= tagCount;
                            state.pos += count;
                            continue;
                        }

                        if (res.can_open) {
                            stack += tagCount;
                        }
                        state.pos += count;
                        continue;
                    }

                    state.md.inline.skipToken(state);
                }

                if (!found) {
                    // parser failed to find ending tag, so it's not valid emphasis
                    state.pos = start;
                    return false;
                }

                // found!
                state.posMax = state.pos;
                state.pos = start + 2;

                // Earlier we checked !silent, but this implementation does not need it
                state.push({type: 's_open', level: state.level++});
                state.md.inline.tokenize(state);
                state.push({type: 's_close', level: --state.level});

                state.pos = state.posMax + 2;
                state.posMax = max;
                return true;
            };

        }, {}],
        50: [function (require, module, exports) {
// Skip text characters for text token, place those to pending buffer
// and increment current pos

            'use strict';


// Rule to skip pure text
// '{}$%@~+=:' reserved for extentions

// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~

// !!!! Don't confuse with "Markdown ASCII Punctuation" chars
// http://spec.commonmark.org/0.15/#ascii-punctuation-character
            function isTerminatorChar(ch) {
                switch (ch) {
                    case 0x0A/* \n */
                    :
                    case 0x21/* ! */
                    :
                    case 0x23/* # */
                    :
                    case 0x24/* $ */
                    :
                    case 0x25/* % */
                    :
                    case 0x26/* & */
                    :
                    case 0x2A/* * */
                    :
                    case 0x2B/* + */
                    :
                    case 0x2D/* - */
                    :
                    case 0x3A/* : */
                    :
                    case 0x3C/* < */
                    :
                    case 0x3D/* = */
                    :
                    case 0x3E/* > */
                    :
                    case 0x40/* @ */
                    :
                    case 0x5B/* [ */
                    :
                    case 0x5C/* \ */
                    :
                    case 0x5D/* ] */
                    :
                    case 0x5E/* ^ */
                    :
                    case 0x5F/* _ */
                    :
                    case 0x60/* ` */
                    :
                    case 0x7B/* { */
                    :
                    case 0x7D/* } */
                    :
                    case 0x7E/* ~ */
                    :
                        return true;
                    default:
                        return false;
                }
            }

            module.exports = function text(state, silent) {
                var pos = state.pos;

                while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) {
                    pos++;
                }

                if (pos === state.pos) {
                    return false;
                }

                if (!silent) {
                    state.pending += state.src.slice(state.pos, pos);
                }

                state.pos = pos;

                return true;
            };

        }, {}],
        51: [function (require, module, exports) {
            (function (root, factory) {
                if (typeof define === 'function' && define.amd) {
                    // AMD. Register as an anonymous module.
                    define([], function () {
                        return (root.returnExportsGlobal = factory());
                    });
                } else if (typeof exports === 'object') {
                    // Node. Does not work with strict CommonJS, but
                    // only CommonJS-like enviroments that support module.exports,
                    // like Node.
                    module.exports = factory();
                } else {
                    root['Autolinker'] = factory();
                }
            }(this, function () {

                /*!
                 * Autolinker.js
                 * 0.15.0
                 *
                 * Copyright(c) 2014 Gregory Jacobs <greg@greg-jacobs.com>
                 * MIT Licensed. http://www.opensource.org/licenses/mit-license.php
                 *
                 * https://github.com/gregjacobs/Autolinker.js
                 */
                /**
                 * @class Autolinker
                 * @extends Object
                 *
                 * Utility class used to process a given string of text, and wrap the URLs, email addresses, and Twitter handles in
                 * the appropriate anchor (&lt;a&gt;) tags to turn them into links.
                 *
                 * Any of the configuration options may be provided in an Object (map) provided to the Autolinker constructor, which
                 * will configure how the {@link #link link()} method will process the links.
                 *
                 * For example:
                 *
                 *     var autolinker = new Autolinker( {
   *         newWindow : false,
   *         truncate  : 30
   *     } );
                 *
                 *     var html = autolinker.link( "Joe went to www.yahoo.com" );
                 *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>'
                 *
                 *
                 * The {@link #static-link static link()} method may also be used to inline options into a single call, which may
                 * be more convenient for one-off uses. For example:
                 *
                 *     var html = Autolinker.link( "Joe went to www.yahoo.com", {
   *         newWindow : false,
   *         truncate  : 30
   *     } );
                 *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>'
                 *
                 *
                 * ## Custom Replacements of Links
                 *
                 * If the configuration options do not provide enough flexibility, a {@link #replaceFn} may be provided to fully customize
                 * the output of Autolinker. This function is called once for each URL/Email/Twitter handle match that is encountered.
                 *
                 * For example:
                 *
                 *     var input = "...";  // string with URLs, Email Addresses, and Twitter Handles
                 *
                 *     var linkedText = Autolinker.link( input, {
   *         replaceFn : function( autolinker, match ) {
   *             console.log( "href = ", match.getAnchorHref() );
   *             console.log( "text = ", match.getAnchorText() );
   *
   *             switch( match.getType() ) {
   *                 case 'url' :
   *                     console.log( "url: ", match.getUrl() );
   *
   *                     if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) {
   *                         var tag = autolinker.getTagBuilder().build( match );  // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes
   *                         tag.setAttr( 'rel', 'nofollow' );
   *                         tag.addClass( 'external-link' );
   *
   *                         return tag;
   *
   *                     } else {
   *                         return true;  // let Autolinker perform its normal anchor tag replacement
   *                     }
   *
   *                 case 'email' :
   *                     var email = match.getEmail();
   *                     console.log( "email: ", email );
   *
   *                     if( email === "my@own.address" ) {
   *                         return false;  // don't auto-link this particular email address; leave as-is
   *                     } else {
   *                         return;  // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`)
   *                     }
   *
   *                 case 'twitter' :
   *                     var twitterHandle = match.getTwitterHandle();
   *                     console.log( twitterHandle );
   *
   *                     return '<a href="http://newplace.to.link.twitter.handles.to/">' + twitterHandle + '</a>';
   *             }
   *         }
   *     } );
                 *
                 *
                 * The function may return the following values:
                 *
                 * - `true` (Boolean): Allow Autolinker to replace the match as it normally would.
                 * - `false` (Boolean): Do not replace the current match at all - leave as-is.
                 * - Any String: If a string is returned from the function, the string will be used directly as the replacement HTML for
                 *   the match.
                 * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify an HTML tag before writing out its HTML text.
                 *
                 * @constructor
                 * @param {Object} [config] The configuration options for the Autolinker instance, specified in an Object (map).
                 */
                var Autolinker = function (cfg) {
                    Autolinker.Util.assign(this, cfg);  // assign the properties of `cfg` onto the Autolinker instance. Prototype properties will be used for missing configs.

                    this.matchValidator = new Autolinker.MatchValidator();
                };


                Autolinker.prototype = {
                    constructor: Autolinker,  // fix constructor property

                    /**
                     * @cfg {Boolean} urls
                     *
                     * `true` if miscellaneous URLs should be automatically linked, `false` if they should not be.
                     */
                    urls: true,

                    /**
                     * @cfg {Boolean} email
                     *
                     * `true` if email addresses should be automatically linked, `false` if they should not be.
                     */
                    email: true,

                    /**
                     * @cfg {Boolean} twitter
                     *
                     * `true` if Twitter handles ("@example") should be automatically linked, `false` if they should not be.
                     */
                    twitter: true,

                    /**
                     * @cfg {Boolean} newWindow
                     *
                     * `true` if the links should open in a new window, `false` otherwise.
                     */
                    newWindow: true,

                    /**
                     * @cfg {Boolean} stripPrefix
                     *
                     * `true` if 'http://' or 'https://' and/or the 'www.' should be stripped from the beginning of URL links' text,
                     * `false` otherwise.
                     */
                    stripPrefix: true,

                    /**
                     * @cfg {Number} truncate
                     *
                     * A number for how many characters long URLs/emails/twitter handles should be truncated to inside the text of
                     * a link. If the URL/email/twitter is over this number of characters, it will be truncated to this length by
                     * adding a two period ellipsis ('..') to the end of the string.
                     *
                     * For example: A url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters might look
                     * something like this: 'yahoo.com/some/long/pat..'
                     */

                    /**
                     * @cfg {String} className
                     *
                     * A CSS class name to add to the generated links. This class will be added to all links, as well as this class
                     * plus url/email/twitter suffixes for styling url/email/twitter links differently.
                     *
                     * For example, if this config is provided as "myLink", then:
                     *
                     * - URL links will have the CSS classes: "myLink myLink-url"
                     * - Email links will have the CSS classes: "myLink myLink-email", and
                     * - Twitter links will have the CSS classes: "myLink myLink-twitter"
                     */
                    className: "",

                    /**
                     * @cfg {Function} replaceFn
                     *
                     * A function to individually process each URL/Email/Twitter match found in the input string.
                     *
                     * See the class's description for usage.
                     *
                     * This function is called with the following parameters:
                     *
                     * @cfg {Autolinker} replaceFn.autolinker The Autolinker instance, which may be used to retrieve child objects from (such
                     *   as the instance's {@link #getTagBuilder tag builder}).
                     * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which can be used to retrieve information about the
                     *   {@link Autolinker.match.Url URL}/{@link Autolinker.match.Email email}/{@link Autolinker.match.Twitter Twitter}
                     *   match that the `replaceFn` is currently processing.
                     */


                    /**
                     * @private
                     * @property {RegExp} htmlCharacterEntitiesRegex
                     *
                     * The regular expression that matches common HTML character entities.
                     *
                     * Ignoring &amp; as it could be part of a query string -- handling it separately.
                     */
                    htmlCharacterEntitiesRegex: /(&nbsp;|&#160;|&lt;|&#60;|&gt;|&#62;)/gi,

                    /**
                     * @private
                     * @property {RegExp} matcherRegex
                     *
                     * The regular expression that matches URLs, email addresses, and Twitter handles.
                     *
                     * This regular expression has the following capturing groups:
                     *
                     * 1. Group that is used to determine if there is a Twitter handle match (i.e. \@someTwitterUser). Simply check for its
                     *    existence to determine if there is a Twitter handle match. The next couple of capturing groups give information
                     *    about the Twitter handle match.
                     * 2. The whitespace character before the \@sign in a Twitter handle. This is needed because there are no lookbehinds in
                     *    JS regular expressions, and can be used to reconstruct the original string in a replace().
                     * 3. The Twitter handle itself in a Twitter match. If the match is '@someTwitterUser', the handle is 'someTwitterUser'.
                     * 4. Group that matches an email address. Used to determine if the match is an email address, as well as holding the full
                     *    address. Ex: 'me@my.com'
                     * 5. Group that matches a URL in the input text. Ex: 'http://google.com', 'www.google.com', or just 'google.com'.
                     *    This also includes a path, url parameters, or hash anchors. Ex: google.com/path/to/file?q1=1&q2=2#myAnchor
                     * 6. Group that matches a protocol URL (i.e. 'http://google.com'). This is used to match protocol URLs with just a single
                     *    word, like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
                     * 7. A protocol-relative ('//') match for the case of a 'www.' prefixed URL. Will be an empty string if it is not a
                     *    protocol-relative match. We need to know the character before the '//' in order to determine if it is a valid match
                     *    or the // was in a string we don't want to auto-link.
                     * 8. A protocol-relative ('//') match for the case of a known TLD prefixed URL. Will be an empty string if it is not a
                     *    protocol-relative match. See #6 for more info.
                     */
                    matcherRegex: (function () {
                        var twitterRegex = /(^|[^\w])@(\w{1,15})/,              // For matching a twitter handle. Ex: @gregory_jacobs

                            emailRegex = /(?:[\-;:&=\+\$,\w\.]+@)/,             // something@ for email addresses (a.k.a. local-part)

                            protocolRegex = /(?:[A-Za-z][-.+A-Za-z0-9]+:(?![A-Za-z][-.+A-Za-z0-9]+:\/\/)(?!\d+\/?)(?:\/\/)?)/,  // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex)
                            wwwRegex = /(?:www\.)/,                             // starting with 'www.'
                            domainNameRegex = /[A-Za-z0-9\.\-]*[A-Za-z0-9\-]/,  // anything looking at all like a domain, non-unicode domains, not ending in a period
                            tldRegex = /\.(?:international|construction|contractors|enterprises|photography|productions|foundation|immobilien|industries|management|properties|technology|christmas|community|directory|education|equipment|institute|marketing|solutions|vacations|bargains|boutique|builders|catering|cleaning|clothing|computer|democrat|diamonds|graphics|holdings|lighting|partners|plumbing|supplies|training|ventures|academy|careers|company|cruises|domains|exposed|flights|florist|gallery|guitars|holiday|kitchen|neustar|okinawa|recipes|rentals|reviews|shiksha|singles|support|systems|agency|berlin|camera|center|coffee|condos|dating|estate|events|expert|futbol|kaufen|luxury|maison|monash|museum|nagoya|photos|repair|report|social|supply|tattoo|tienda|travel|viajes|villas|vision|voting|voyage|actor|build|cards|cheap|codes|dance|email|glass|house|mango|ninja|parts|photo|shoes|solar|today|tokyo|tools|watch|works|aero|arpa|asia|best|bike|blue|buzz|camp|club|cool|coop|farm|fish|gift|guru|info|jobs|kiwi|kred|land|limo|link|menu|mobi|moda|name|pics|pink|post|qpon|rich|ruhr|sexy|tips|vote|voto|wang|wien|wiki|zone|bar|bid|biz|cab|cat|ceo|com|edu|gov|int|kim|mil|net|onl|org|pro|pub|red|tel|uno|wed|xxx|xyz|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/,   // match our known top level domains (TLDs)

                        // Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;"
                        // http://blog.codinghorror.com/the-problem-with-urls/
                            urlSuffixRegex = /[\-A-Za-z0-9+&@#\/%=~_()|'$*\[\]?!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|'$*\[\]]/;

                        return new RegExp([
                            '(',  // *** Capturing group $1, which can be used to check for a twitter handle match. Use group $3 for the actual twitter handle though. $2 may be used to reconstruct the original string in a replace()
                            // *** Capturing group $2, which matches the whitespace character before the '@' sign (needed because of no lookbehinds), and
                            // *** Capturing group $3, which matches the actual twitter handle
                            twitterRegex.source,
                            ')',

                            '|',

                            '(',  // *** Capturing group $4, which is used to determine an email match
                            emailRegex.source,
                            domainNameRegex.source,
                            tldRegex.source,
                            ')',

                            '|',

                            '(',  // *** Capturing group $5, which is used to match a URL
                            '(?:', // parens to cover match for protocol (optional), and domain
                            '(',  // *** Capturing group $6, for a protocol-prefixed url (ex: http://google.com)
                            protocolRegex.source,
                            domainNameRegex.source,
                            ')',

                            '|',

                            '(?:',  // non-capturing paren for a 'www.' prefixed url (ex: www.google.com)
                            '(.?//)?',  // *** Capturing group $7 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character
                            wwwRegex.source,
                            domainNameRegex.source,
                            ')',

                            '|',

                            '(?:',  // non-capturing paren for known a TLD url (ex: google.com)
                            '(.?//)?',  // *** Capturing group $8 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character
                            domainNameRegex.source,
                            tldRegex.source,
                            ')',
                            ')',

                            '(?:' + urlSuffixRegex.source + ')?',  // match for path, query string, and/or hash anchor - optional
                            ')'
                        ].join(""), 'gi');
                    })(),

                    /**
                     * @private
                     * @property {RegExp} charBeforeProtocolRelMatchRegex
                     *
                     * The regular expression used to retrieve the character before a protocol-relative URL match.
                     *
                     * This is used in conjunction with the {@link #matcherRegex}, which needs to grab the character before a protocol-relative
                     * '//' due to the lack of a negative look-behind in JavaScript regular expressions. The character before the match is stripped
                     * from the URL.
                     */
                    charBeforeProtocolRelMatchRegex: /^(.)?\/\//,

                    /**
                     * @private
                     * @property {Autolinker.MatchValidator} matchValidator
                     *
                     * The MatchValidator object, used to filter out any false positives from the {@link #matcherRegex}. See
                     * {@link Autolinker.MatchValidator} for details.
                     */

                    /**
                     * @private
                     * @property {Autolinker.HtmlParser} htmlParser
                     *
                     * The HtmlParser instance used to skip over HTML tags, while finding text nodes to process. This is lazily instantiated
                     * in the {@link #getHtmlParser} method.
                     */

                    /**
                     * @private
                     * @property {Autolinker.AnchorTagBuilder} tagBuilder
                     *
                     * The AnchorTagBuilder instance used to build the URL/email/Twitter replacement anchor tags. This is lazily instantiated
                     * in the {@link #getTagBuilder} method.
                     */


                    /**
                     * Automatically links URLs, email addresses, and Twitter handles found in the given chunk of HTML.
                     * Does not link URLs found within HTML tags.
                     *
                     * For instance, if given the text: `You should go to http://www.yahoo.com`, then the result
                     * will be `You should go to &lt;a href="http://www.yahoo.com"&gt;http://www.yahoo.com&lt;/a&gt;`
                     *
                     * This method finds the text around any HTML elements in the input `textOrHtml`, which will be the text that is processed.
                     * Any original HTML elements will be left as-is, as well as the text that is already wrapped in anchor (&lt;a&gt;) tags.
                     *
                     * @param {String} textOrHtml The HTML or text to link URLs, email addresses, and Twitter handles within (depending on if
                     *   the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled).
                     * @return {String} The HTML, with URLs/emails/Twitter handles automatically linked.
                     */
                    link: function (textOrHtml) {
                        var me = this,  // for closure
                            htmlParser = this.getHtmlParser(),
                            htmlCharacterEntitiesRegex = this.htmlCharacterEntitiesRegex,
                            anchorTagStackCount = 0,  // used to only process text around anchor tags, and any inner text/html they may have
                            resultHtml = [];

                        htmlParser.parse(textOrHtml, {
                            // Process HTML nodes in the input `textOrHtml`
                            processHtmlNode: function (tagText, tagName, isClosingTag) {
                                if (tagName === 'a') {
                                    if (!isClosingTag) {  // it's the start <a> tag
                                        anchorTagStackCount++;
                                    } else {   // it's the end </a> tag
                                        anchorTagStackCount = Math.max(anchorTagStackCount - 1, 0);  // attempt to handle extraneous </a> tags by making sure the stack count never goes below 0
                                    }
                                }
                                resultHtml.push(tagText);  // now add the text of the tag itself verbatim
                            },

                            // Process text nodes in the input `textOrHtml`
                            processTextNode: function (text) {
                                if (anchorTagStackCount === 0) {
                                    // If we're not within an <a> tag, process the text node
                                    var unescapedText = Autolinker.Util.splitAndCapture(text, htmlCharacterEntitiesRegex);  // split at HTML entities, but include the HTML entities in the results array

                                    for (var i = 0, len = unescapedText.length; i < len; i++) {
                                        var textToProcess = unescapedText[i],
                                            processedTextNode = me.processTextNode(textToProcess);

                                        resultHtml.push(processedTextNode);
                                    }

                                } else {
                                    // `text` is within an <a> tag, simply append the text - we do not want to autolink anything
                                    // already within an <a>...</a> tag
                                    resultHtml.push(text);
                                }
                            }
                        });

                        return resultHtml.join("");
                    },


                    /**
                     * Lazily instantiates and returns the {@link #htmlParser} instance for this Autolinker instance.
                     *
                     * @protected
                     * @return {Autolinker.HtmlParser}
                     */
                    getHtmlParser: function () {
                        var htmlParser = this.htmlParser;

                        if (!htmlParser) {
                            htmlParser = this.htmlParser = new Autolinker.HtmlParser();
                        }

                        return htmlParser;
                    },


                    /**
                     * Returns the {@link #tagBuilder} instance for this Autolinker instance, lazily instantiating it
                     * if it does not yet exist.
                     *
                     * This method may be used in a {@link #replaceFn} to generate the {@link Autolinker.HtmlTag HtmlTag} instance that
                     * Autolinker would normally generate, and then allow for modifications before returning it. For example:
                     *
                     *     var html = Autolinker.link( "Test google.com", {
     *         replaceFn : function( autolinker, match ) {
     *             var tag = autolinker.getTagBuilder().build( match );  // returns an {@link Autolinker.HtmlTag} instance
     *             tag.setAttr( 'rel', 'nofollow' );
     *
     *             return tag;
     *         }
     *     } );
                     *
                     *     // generated html:
                     *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
                     *
                     * @return {Autolinker.AnchorTagBuilder}
                     */
                    getTagBuilder: function () {
                        var tagBuilder = this.tagBuilder;

                        if (!tagBuilder) {
                            tagBuilder = this.tagBuilder = new Autolinker.AnchorTagBuilder({
                                newWindow: this.newWindow,
                                truncate: this.truncate,
                                className: this.className
                            });
                        }

                        return tagBuilder;
                    },


                    /**
                     * Process the text that lies inbetween HTML tags. This method does the actual wrapping of URLs with
                     * anchor tags.
                     *
                     * @private
                     * @param {String} text The text to auto-link.
                     * @return {String} The text with anchor tags auto-filled.
                     */
                    processTextNode: function (text) {
                        var me = this;  // for closure

                        return text.replace(this.matcherRegex, function (matchStr, $1, $2, $3, $4, $5, $6, $7, $8) {
                            var matchDescObj = me.processCandidateMatch(matchStr, $1, $2, $3, $4, $5, $6, $7, $8);  // match description object

                            // Return out with no changes for match types that are disabled (url, email, twitter), or for matches that are
                            // invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
                            if (!matchDescObj) {
                                return matchStr;

                            } else {
                                // Generate the replacement text for the match
                                var matchReturnVal = me.createMatchReturnVal(matchDescObj.match, matchDescObj.matchStr);
                                return matchDescObj.prefixStr + matchReturnVal + matchDescObj.suffixStr;
                            }
                        });
                    },


                    /**
                     * Processes a candidate match from the {@link #matcherRegex}.
                     *
                     * Not all matches found by the regex are actual URL/email/Twitter matches, as determined by the {@link #matchValidator}. In
                     * this case, the method returns `null`. Otherwise, a valid Object with `prefixStr`, `match`, and `suffixStr` is returned.
                     *
                     * @private
                     * @param {String} matchStr The full match that was found by the {@link #matcherRegex}.
                     * @param {String} twitterMatch The matched text of a Twitter handle, if the match is a Twitter match.
                     * @param {String} twitterHandlePrefixWhitespaceChar The whitespace char before the @ sign in a Twitter handle match. This
                     *   is needed because of no lookbehinds in JS regexes, and is need to re-include the character for the anchor tag replacement.
                     * @param {String} twitterHandle The actual Twitter user (i.e the word after the @ sign in a Twitter match).
                     * @param {String} emailAddressMatch The matched email address for an email address match.
                     * @param {String} urlMatch The matched URL string for a URL match.
                     * @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to match
                     *   something like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
                     * @param {String} wwwProtocolRelativeMatch The '//' for a protocol-relative match from a 'www' url, with the character that
                     *   comes before the '//'.
                     * @param {String} tldProtocolRelativeMatch The '//' for a protocol-relative match from a TLD (top level domain) match, with
                     *   the character that comes before the '//'.
                     *
                     * @return {Object} A "match description object". This will be `null` if the match was invalid, or if a match type is disabled.
                     *   Otherwise, this will be an Object (map) with the following properties:
                     * @return {String} return.prefixStr The char(s) that should be prepended to the replacement string. These are char(s) that
                     *   were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into
                     *   the replacement stream.
                     * @return {String} return.suffixStr The char(s) that should be appended to the replacement string. These are char(s) that
                     *   were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into
                     *   the replacement stream.
                     * @return {String} return.matchStr The `matchStr`, fixed up to remove characters that are no longer needed (which have been
                     *   added to `prefixStr` and `suffixStr`).
                     * @return {Autolinker.match.Match} return.match The Match object that represents the match that was found.
                     */
                    processCandidateMatch: function (matchStr, twitterMatch, twitterHandlePrefixWhitespaceChar, twitterHandle,
                                                     emailAddressMatch, urlMatch, protocolUrlMatch, wwwProtocolRelativeMatch, tldProtocolRelativeMatch) {
                        var protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch,
                            match,  // Will be an Autolinker.match.Match object

                            prefixStr = "",       // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match
                            suffixStr = "";       // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked.


                        // Return out with `null` for match types that are disabled (url, email, twitter), or for matches that are
                        // invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
                        if (
                            ( twitterMatch && !this.twitter ) || ( emailAddressMatch && !this.email ) || ( urlMatch && !this.urls ) || !this.matchValidator.isValidMatch(urlMatch, protocolUrlMatch, protocolRelativeMatch)
                        ) {
                            return null;
                        }

                        // Handle a closing parenthesis at the end of the match, and exclude it if there is not a matching open parenthesis
                        // in the match itself.
                        if (this.matchHasUnbalancedClosingParen(matchStr)) {
                            matchStr = matchStr.substr(0, matchStr.length - 1);  // remove the trailing ")"
                            suffixStr = ")";  // this will be added after the generated <a> tag
                        }


                        if (emailAddressMatch) {
                            match = new Autolinker.match.Email({matchedText: matchStr, email: emailAddressMatch});

                        } else if (twitterMatch) {
                            // fix up the `matchStr` if there was a preceding whitespace char, which was needed to determine the match
                            // itself (since there are no look-behinds in JS regexes)
                            if (twitterHandlePrefixWhitespaceChar) {
                                prefixStr = twitterHandlePrefixWhitespaceChar;
                                matchStr = matchStr.slice(1);  // remove the prefixed whitespace char from the match
                            }
                            match = new Autolinker.match.Twitter({matchedText: matchStr, twitterHandle: twitterHandle});

                        } else {  // url match
                            // If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed
                            // to match due to the lack of a negative look-behind in JavaScript regular expressions)
                            if (protocolRelativeMatch) {
                                var charBeforeMatch = protocolRelativeMatch.match(this.charBeforeProtocolRelMatchRegex)[1] || "";

                                if (charBeforeMatch) {  // fix up the `matchStr` if there was a preceding char before a protocol-relative match, which was needed to determine the match itself (since there are no look-behinds in JS regexes)
                                    prefixStr = charBeforeMatch;
                                    matchStr = matchStr.slice(1);  // remove the prefixed char from the match
                                }
                            }

                            match = new Autolinker.match.Url({
                                matchedText: matchStr,
                                url: matchStr,
                                protocolUrlMatch: !!protocolUrlMatch,
                                protocolRelativeMatch: !!protocolRelativeMatch,
                                stripPrefix: this.stripPrefix
                            });
                        }

                        return {
                            prefixStr: prefixStr,
                            suffixStr: suffixStr,
                            matchStr: matchStr,
                            match: match
                        };
                    },


                    /**
                     * Determines if a match found has an unmatched closing parenthesis. If so, this parenthesis will be removed
                     * from the match itself, and appended after the generated anchor tag in {@link #processTextNode}.
                     *
                     * A match may have an extra closing parenthesis at the end of the match because the regular expression must include parenthesis
                     * for URLs such as "wikipedia.com/something_(disambiguation)", which should be auto-linked.
                     *
                     * However, an extra parenthesis *will* be included when the URL itself is wrapped in parenthesis, such as in the case of
                     * "(wikipedia.com/something_(disambiguation))". In this case, the last closing parenthesis should *not* be part of the URL
                     * itself, and this method will return `true`.
                     *
                     * @private
                     * @param {String} matchStr The full match string from the {@link #matcherRegex}.
                     * @return {Boolean} `true` if there is an unbalanced closing parenthesis at the end of the `matchStr`, `false` otherwise.
                     */
                    matchHasUnbalancedClosingParen: function (matchStr) {
                        var lastChar = matchStr.charAt(matchStr.length - 1);

                        if (lastChar === ')') {
                            var openParensMatch = matchStr.match(/\(/g),
                                closeParensMatch = matchStr.match(/\)/g),
                                numOpenParens = ( openParensMatch && openParensMatch.length ) || 0,
                                numCloseParens = ( closeParensMatch && closeParensMatch.length ) || 0;

                            if (numOpenParens < numCloseParens) {
                                return true;
                            }
                        }

                        return false;
                    },


                    /**
                     * Creates the return string value for a given match in the input string, for the {@link #processTextNode} method.
                     *
                     * This method handles the {@link #replaceFn}, if one was provided.
                     *
                     * @private
                     * @param {Autolinker.match.Match} match The Match object that represents the match.
                     * @param {String} matchStr The original match string, after having been preprocessed to fix match edge cases (see
                     *   the `prefixStr` and `suffixStr` vars in {@link #processTextNode}.
                     * @return {String} The string that the `match` should be replaced with. This is usually the anchor tag string, but
                     *   may be the `matchStr` itself if the match is not to be replaced.
                     */
                    createMatchReturnVal: function (match, matchStr) {
                        // Handle a custom `replaceFn` being provided
                        var replaceFnResult;
                        if (this.replaceFn) {
                            replaceFnResult = this.replaceFn.call(this, this, match);  // Autolinker instance is the context, and the first arg
                        }

                        if (typeof replaceFnResult === 'string') {
                            return replaceFnResult;  // `replaceFn` returned a string, use that

                        } else if (replaceFnResult === false) {
                            return matchStr;  // no replacement for the match

                        } else if (replaceFnResult instanceof Autolinker.HtmlTag) {
                            return replaceFnResult.toString();

                        } else {  // replaceFnResult === true, or no/unknown return value from function
                            // Perform Autolinker's default anchor tag generation
                            var tagBuilder = this.getTagBuilder(),
                                anchorTag = tagBuilder.build(match);  // returns an Autolinker.HtmlTag instance

                            return anchorTag.toString();
                        }
                    }

                };


                /**
                 * Automatically links URLs, email addresses, and Twitter handles found in the given chunk of HTML.
                 * Does not link URLs found within HTML tags.
                 *
                 * For instance, if given the text: `You should go to http://www.yahoo.com`, then the result
                 * will be `You should go to &lt;a href="http://www.yahoo.com"&gt;http://www.yahoo.com&lt;/a&gt;`
                 *
                 * Example:
                 *
                 *     var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } );
                 *     // Produces: "Go to <a href="http://google.com">google.com</a>"
                 *
                 * @static
                 * @param {String} textOrHtml The HTML or text to find URLs, email addresses, and Twitter handles within (depending on if
                 *   the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled).
                 * @param {Object} [options] Any of the configuration options for the Autolinker class, specified in an Object (map).
                 *   See the class description for an example call.
                 * @return {String} The HTML text, with URLs automatically linked
                 */
                Autolinker.link = function (textOrHtml, options) {
                    var autolinker = new Autolinker(options);
                    return autolinker.link(textOrHtml);
                };


                // Namespace for `match` classes
                Autolinker.match = {};
                /*global Autolinker */
                /*jshint eqnull:true, boss:true */
                /**
                 * @class Autolinker.Util
                 * @singleton
                 *
                 * A few utility methods for Autolinker.
                 */
                Autolinker.Util = {

                    /**
                     * @property {Function} abstractMethod
                     *
                     * A function object which represents an abstract method.
                     */
                    abstractMethod: function () {
                        throw "abstract";
                    },


                    /**
                     * Assigns (shallow copies) the properties of `src` onto `dest`.
                     *
                     * @param {Object} dest The destination object.
                     * @param {Object} src The source object.
                     * @return {Object} The destination object (`dest`)
                     */
                    assign: function (dest, src) {
                        for (var prop in src) {
                            if (src.hasOwnProperty(prop)) {
                                dest[prop] = src[prop];
                            }
                        }

                        return dest;
                    },


                    /**
                     * Extends `superclass` to create a new subclass, adding the `protoProps` to the new subclass's prototype.
                     *
                     * @param {Function} superclass The constructor function for the superclass.
                     * @param {Object} protoProps The methods/properties to add to the subclass's prototype. This may contain the
                     *   special property `constructor`, which will be used as the new subclass's constructor function.
                     * @return {Function} The new subclass function.
                     */
                    extend: function (superclass, protoProps) {
                        var superclassProto = superclass.prototype;

                        var F = function () {
                        };
                        F.prototype = superclassProto;

                        var subclass;
                        if (protoProps.hasOwnProperty('constructor')) {
                            subclass = protoProps.constructor;
                        } else {
                            subclass = function () {
                                superclassProto.constructor.apply(this, arguments);
                            };
                        }

                        var subclassProto = subclass.prototype = new F();  // set up prototype chain
                        subclassProto.constructor = subclass;  // fix constructor property
                        subclassProto.superclass = superclassProto;

                        delete protoProps.constructor;  // don't re-assign constructor property to the prototype, since a new function may have been created (`subclass`), which is now already there
                        Autolinker.Util.assign(subclassProto, protoProps);

                        return subclass;
                    },


                    /**
                     * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the
                     * end of the string (by default, two periods: '..'). If the `str` length does not exceed
                     * `len`, the string will be returned unchanged.
                     *
                     * @param {String} str The string to truncate and add an ellipsis to.
                     * @param {Number} truncateLen The length to truncate the string at.
                     * @param {String} [ellipsisChars=..] The ellipsis character(s) to add to the end of `str`
                     *   when truncated. Defaults to '..'
                     */
                    ellipsis: function (str, truncateLen, ellipsisChars) {
                        if (str.length > truncateLen) {
                            ellipsisChars = ( ellipsisChars == null ) ? '..' : ellipsisChars;
                            str = str.substring(0, truncateLen - ellipsisChars.length) + ellipsisChars;
                        }
                        return str;
                    },


                    /**
                     * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below).
                     *
                     * @param {Array} arr The array to find an element of.
                     * @param {*} element The element to find in the array, and return the index of.
                     * @return {Number} The index of the `element`, or -1 if it was not found.
                     */
                    indexOf: function (arr, element) {
                        if (Array.prototype.indexOf) {
                            return arr.indexOf(element);

                        } else {
                            for (var i = 0, len = arr.length; i < len; i++) {
                                if (arr[i] === element) return i;
                            }
                            return -1;
                        }
                    },


                    /**
                     * Performs the functionality of what modern browsers do when `String.prototype.split()` is called
                     * with a regular expression that contains capturing parenthesis.
                     *
                     * For example:
                     *
                     *     // Modern browsers:
                     *     "a,b,c".split( /(,)/ );  // --> [ 'a', ',', 'b', ',', 'c' ]
                     *
                     *     // Old IE (including IE8):
                     *     "a,b,c".split( /(,)/ );  // --> [ 'a', 'b', 'c' ]
                     *
                     * This method emulates the functionality of modern browsers for the old IE case.
                     *
                     * @param {String} str The string to split.
                     * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting
                     *   character(s) will be spliced into the array, as in the "modern browsers" example in the
                     *   description of this method.
                     *   Note #1: the supplied regular expression **must** have the 'g' flag specified.
                     *   Note #2: for simplicity's sake, the regular expression does not need
                     *   to contain capturing parenthesis - it will be assumed that any match has them.
                     * @return {String[]} The split array of strings, with the splitting character(s) included.
                     */
                    splitAndCapture: function (str, splitRegex) {
                        if (!splitRegex.global) throw new Error("`splitRegex` must have the 'g' flag set");

                        var result = [],
                            lastIdx = 0,
                            match;

                        while (match = splitRegex.exec(str)) {
                            result.push(str.substring(lastIdx, match.index));
                            result.push(match[0]);  // push the splitting char(s)

                            lastIdx = match.index + match[0].length;
                        }
                        result.push(str.substring(lastIdx));

                        return result;
                    }

                };
                /*global Autolinker */
                /**
                 * @private
                 * @class Autolinker.HtmlParser
                 * @extends Object
                 *
                 * An HTML parser implementation which simply walks an HTML string and calls the provided visitor functions to process
                 * HTML and text nodes.
                 *
                 * Autolinker uses this to only link URLs/emails/Twitter handles within text nodes, basically ignoring HTML tags.
                 */
                Autolinker.HtmlParser = Autolinker.Util.extend(Object, {

                    /**
                     * @private
                     * @property {RegExp} htmlRegex
                     *
                     * The regular expression used to pull out HTML tags from a string. Handles namespaced HTML tags and
                     * attribute names, as specified by http://www.w3.org/TR/html-markup/syntax.html.
                     *
                     * Capturing groups:
                     *
                     * 1. The "!DOCTYPE" tag name, if a tag is a &lt;!DOCTYPE&gt; tag.
                     * 2. If it is an end tag, this group will have the '/'.
                     * 3. The tag name for all tags (other than the &lt;!DOCTYPE&gt; tag)
                     */
                    htmlRegex: (function () {
                        var tagNameRegex = /[0-9a-zA-Z][0-9a-zA-Z:]*/,
                            attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/,   // the unicode range accounts for excluding control chars, and the delete char
                            attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values
                            nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?';  // optional '=[value]'

                        return new RegExp([
                            // for <!DOCTYPE> tag. Ex: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
                            '(?:',
                            '<(!DOCTYPE)',  // *** Capturing Group 1 - If it's a doctype tag

                            // Zero or more attributes following the tag name
                            '(?:',
                            '\\s+',  // one or more whitespace chars before an attribute

                            // Either:
                            // A. attr="value", or
                            // B. "value" alone (To cover example doctype tag: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">)
                            '(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')',
                            ')*',
                            '>',
                            ')',

                            '|',

                            // All other HTML tags (i.e. tags that are not <!DOCTYPE>)
                            '(?:',
                            '<(/)?',  // Beginning of a tag. Either '<' for a start tag, or '</' for an end tag.
                                      // *** Capturing Group 2: The slash or an empty string. Slash ('/') for end tag, empty string for start or self-closing tag.

                            // *** Capturing Group 3 - The tag name
                            '(' + tagNameRegex.source + ')',

                            // Zero or more attributes following the tag name
                            '(?:',
                            '\\s+',                // one or more whitespace chars before an attribute
                            nameEqualsValueRegex,  // attr="value" (with optional ="value" part)
                            ')*',

                            '\\s*/?',  // any trailing spaces and optional '/' before the closing '>'
                            '>',
                            ')'
                        ].join(""), 'gi');
                    })(),


                    /**
                     * Walks an HTML string, calling the `options.processHtmlNode` function for each HTML tag that is encountered, and calling
                     * the `options.processTextNode` function when each text around HTML tags is encountered.
                     *
                     * @param {String} html The HTML to parse.
                     * @param {Object} [options] An Object (map) which may contain the following properties:
                     *
                     * @param {Function} [options.processHtmlNode] A visitor function which allows processing of an encountered HTML node.
                     *   This function is called with the following arguments:
                     * @param {String} [options.processHtmlNode.tagText] The HTML tag text that was found.
                     * @param {String} [options.processHtmlNode.tagName] The tag name for the HTML tag that was found. Ex: 'a' for an anchor tag.
                     * @param {String} [options.processHtmlNode.isClosingTag] `true` if the tag is a closing tag (ex: &lt;/a&gt;), `false` otherwise.
                     *
                     * @param {Function} [options.processTextNode] A visitor function which allows processing of an encountered text node.
                     *   This function is called with the following arguments:
                     * @param {String} [options.processTextNode.text] The text node that was matched.
                     */
                    parse: function (html, options) {
                        options = options || {};

                        var processHtmlNodeVisitor = options.processHtmlNode || function () {
                                },
                            processTextNodeVisitor = options.processTextNode || function () {
                                },
                            htmlRegex = this.htmlRegex,
                            currentResult,
                            lastIndex = 0;

                        // Loop over the HTML string, ignoring HTML tags, and processing the text that lies between them,
                        // wrapping the URLs in anchor tags
                        while (( currentResult = htmlRegex.exec(html) ) !== null) {
                            var tagText = currentResult[0],
                                tagName = currentResult[1] || currentResult[3],  // The <!DOCTYPE> tag (ex: "!DOCTYPE"), or another tag (ex: "a")
                                isClosingTag = !!currentResult[2],
                                inBetweenTagsText = html.substring(lastIndex, currentResult.index);

                            if (inBetweenTagsText) {
                                processTextNodeVisitor(inBetweenTagsText);
                            }

                            processHtmlNodeVisitor(tagText, tagName.toLowerCase(), isClosingTag);

                            lastIndex = currentResult.index + tagText.length;
                        }

                        // Process any remaining text after the last HTML element. Will process all of the text if there were no HTML elements.
                        if (lastIndex < html.length) {
                            var text = html.substring(lastIndex);

                            if (text) {
                                processTextNodeVisitor(text);
                            }
                        }
                    }

                });
                /*global Autolinker */
                /*jshint boss:true */
                /**
                 * @class Autolinker.HtmlTag
                 * @extends Object
                 *
                 * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically.
                 *
                 * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use
                 * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}.
                 *
                 * ## Examples
                 *
                 * Example instantiation:
                 *
                 *     var tag = new Autolinker.HtmlTag( {
   *         tagName : 'a',
   *         attrs   : { 'href': 'http://google.com', 'class': 'external-link' },
   *         innerHtml : 'Google'
   *     } );
                 *
                 *     tag.toString();  // <a href="http://google.com" class="external-link">Google</a>
                 *
                 *     // Individual accessor methods
                 *     tag.getTagName();                 // 'a'
                 *     tag.getAttr( 'href' );            // 'http://google.com'
                 *     tag.hasClass( 'external-link' );  // true
                 *
                 *
                 * Using mutator methods (which may be used in combination with instantiation config properties):
                 *
                 *     var tag = new Autolinker.HtmlTag();
                 *     tag.setTagName( 'a' );
                 *     tag.setAttr( 'href', 'http://google.com' );
                 *     tag.addClass( 'external-link' );
                 *     tag.setInnerHtml( 'Google' );
                 *
                 *     tag.getTagName();                 // 'a'
                 *     tag.getAttr( 'href' );            // 'http://google.com'
                 *     tag.hasClass( 'external-link' );  // true
                 *
                 *     tag.toString();  // <a href="http://google.com" class="external-link">Google</a>
                 *
                 *
                 * ## Example use within a {@link Autolinker#replaceFn replaceFn}
                 *
                 *     var html = Autolinker.link( "Test google.com", {
   *         replaceFn : function( autolinker, match ) {
   *             var tag = autolinker.getTagBuilder().build( match );  // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text
   *             tag.setAttr( 'rel', 'nofollow' );
   *
   *             return tag;
   *         }
   *     } );
                 *
                 *     // generated html:
                 *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
                 *
                 *
                 * ## Example use with a new tag for the replacement
                 *
                 *     var html = Autolinker.link( "Test google.com", {
   *         replaceFn : function( autolinker, match ) {
   *             var tag = new Autolinker.HtmlTag( {
   *                 tagName : 'button',
   *                 attrs   : { 'title': 'Load URL: ' + match.getAnchorHref() },
   *                 innerHtml : 'Load URL: ' + match.getAnchorText()
   *             } );
   *
   *             return tag;
   *         }
   *     } );
                 *
                 *     // generated html:
                 *     //   Test <button title="Load URL: http://google.com">Load URL: google.com</button>
                 */
                Autolinker.HtmlTag = Autolinker.Util.extend(Object, {

                    /**
                     * @cfg {String} tagName
                     *
                     * The tag name. Ex: 'a', 'button', etc.
                     *
                     * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toString}
                     * is executed.
                     */

                    /**
                     * @cfg {Object.<String, String>} attrs
                     *
                     * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the
                     * values are the attribute values.
                     */

                    /**
                     * @cfg {String} innerHtml
                     *
                     * The inner HTML for the tag.
                     *
                     * Note the camel case name on `innerHtml`. Acronyms are camelCased in this utility (such as not to run into the acronym
                     * naming inconsistency that the DOM developers created with `XMLHttpRequest`). You may alternatively use {@link #innerHTML}
                     * if you prefer, but this one is recommended.
                     */

                    /**
                     * @cfg {String} innerHTML
                     *
                     * Alias of {@link #innerHtml}, accepted for consistency with the browser DOM api, but prefer the camelCased version
                     * for acronym names.
                     */


                    /**
                     * @protected
                     * @property {RegExp} whitespaceRegex
                     *
                     * Regular expression used to match whitespace in a string of CSS classes.
                     */
                    whitespaceRegex: /\s+/,


                    /**
                     * @constructor
                     * @param {Object} [cfg] The configuration properties for this class, in an Object (map)
                     */
                    constructor: function (cfg) {
                        Autolinker.Util.assign(this, cfg);

                        this.innerHtml = this.innerHtml || this.innerHTML;  // accept either the camelCased form or the fully capitalized acronym
                    },


                    /**
                     * Sets the tag name that will be used to generate the tag with.
                     *
                     * @param {String} tagName
                     * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
                     */
                    setTagName: function (tagName) {
                        this.tagName = tagName;
                        return this;
                    },


                    /**
                     * Retrieves the tag name.
                     *
                     * @return {String}
                     */
                    getTagName: function () {
                        return this.tagName || "";
                    },


                    /**
                     * Sets an attribute on the HtmlTag.
                     *
                     * @param {String} attrName The attribute name to set.
                     * @param {String} attrValue The attribute value to set.
                     * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
                     */
                    setAttr: function (attrName, attrValue) {
                        var tagAttrs = this.getAttrs();
                        tagAttrs[attrName] = attrValue;

                        return this;
                    },


                    /**
                     * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`.
                     *
                     * @param {String} name The attribute name to retrieve.
                     * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag.
                     */
                    getAttr: function (attrName) {
                        return this.getAttrs()[attrName];
                    },


                    /**
                     * Sets one or more attributes on the HtmlTag.
                     *
                     * @param {Object.<String, String>} attrs A key/value Object (map) of the attributes to set.
                     * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
                     */
                    setAttrs: function (attrs) {
                        var tagAttrs = this.getAttrs();
                        Autolinker.Util.assign(tagAttrs, attrs);

                        return this;
                    },


                    /**
                     * Retrieves the attributes Object (map) for the HtmlTag.
                     *
                     * @return {Object.<String, String>} A key/value object of the attributes for the HtmlTag.
                     */
                    getAttrs: function () {
                        return this.attrs || ( this.attrs = {} );
                    },


                    /**
                     * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag.
                     *
                     * @param {String} cssClass One or more space-separated CSS classes to set (overwrite).
                     * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
                     */
                    setClass: function (cssClass) {
                        return this.setAttr('class', cssClass);
                    },


                    /**
                     * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes.
                     *
                     * @param {String} cssClass One or more space-separated CSS classes to add.
                     * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
                     */
                    addClass: function (cssClass) {
                        var classAttr = this.getClass(),
                            whitespaceRegex = this.whitespaceRegex,
                            indexOf = Autolinker.Util.indexOf,  // to support IE8 and below
                            classes = ( !classAttr ) ? [] : classAttr.split(whitespaceRegex),
                            newClasses = cssClass.split(whitespaceRegex),
                            newClass;

                        while (newClass = newClasses.shift()) {
                            if (indexOf(classes, newClass) === -1) {
                                classes.push(newClass);
                            }
                        }

                        this.getAttrs()['class'] = classes.join(" ");
                        return this;
                    },


                    /**
                     * Convenience method to remove one or more CSS classes from the HtmlTag.
                     *
                     * @param {String} cssClass One or more space-separated CSS classes to remove.
                     * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
                     */
                    removeClass: function (cssClass) {
                        var classAttr = this.getClass(),
                            whitespaceRegex = this.whitespaceRegex,
                            indexOf = Autolinker.Util.indexOf,  // to support IE8 and below
                            classes = ( !classAttr ) ? [] : classAttr.split(whitespaceRegex),
                            removeClasses = cssClass.split(whitespaceRegex),
                            removeClass;

                        while (classes.length && ( removeClass = removeClasses.shift() )) {
                            var idx = indexOf(classes, removeClass);
                            if (idx !== -1) {
                                classes.splice(idx, 1);
                            }
                        }

                        this.getAttrs()['class'] = classes.join(" ");
                        return this;
                    },


                    /**
                     * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when
                     * there are multiple.
                     *
                     * @return {String}
                     */
                    getClass: function () {
                        return this.getAttrs()['class'] || "";
                    },


                    /**
                     * Convenience method to check if the tag has a CSS class or not.
                     *
                     * @param {String} cssClass The CSS class to check for.
                     * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise.
                     */
                    hasClass: function (cssClass) {
                        return ( ' ' + this.getClass() + ' ' ).indexOf(' ' + cssClass + ' ') !== -1;
                    },


                    /**
                     * Sets the inner HTML for the tag.
                     *
                     * @param {String} html The inner HTML to set.
                     * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
                     */
                    setInnerHtml: function (html) {
                        this.innerHtml = html;

                        return this;
                    },


                    /**
                     * Retrieves the inner HTML for the tag.
                     *
                     * @return {String}
                     */
                    getInnerHtml: function () {
                        return this.innerHtml || "";
                    },


                    /**
                     * Override of superclass method used to generate the HTML string for the tag.
                     *
                     * @return {String}
                     */
                    toString: function () {
                        var tagName = this.getTagName(),
                            attrsStr = this.buildAttrsStr();

                        attrsStr = ( attrsStr ) ? ' ' + attrsStr : '';  // prepend a space if there are actually attributes

                        return ['<', tagName, attrsStr, '>', this.getInnerHtml(), '</', tagName, '>'].join("");
                    },


                    /**
                     * Support method for {@link #toString}, returns the string space-separated key="value" pairs, used to populate
                     * the stringified HtmlTag.
                     *
                     * @protected
                     * @return {String} Example return: `attr1="value1" attr2="value2"`
                     */
                    buildAttrsStr: function () {
                        if (!this.attrs) return "";  // no `attrs` Object (map) has been set, return empty string

                        var attrs = this.getAttrs(),
                            attrsArr = [];

                        for (var prop in attrs) {
                            if (attrs.hasOwnProperty(prop)) {
                                attrsArr.push(prop + '="' + attrs[prop] + '"');
                            }
                        }
                        return attrsArr.join(" ");
                    }

                });
                /*global Autolinker */
                /*jshint scripturl:true */
                /**
                 * @private
                 * @class Autolinker.MatchValidator
                 * @extends Object
                 *
                 * Used by Autolinker to filter out false positives from the {@link Autolinker#matcherRegex}.
                 *
                 * Due to the limitations of regular expressions (including the missing feature of look-behinds in JS regular expressions),
                 * we cannot always determine the validity of a given match. This class applies a bit of additional logic to filter out any
                 * false positives that have been matched by the {@link Autolinker#matcherRegex}.
                 */
                Autolinker.MatchValidator = Autolinker.Util.extend(Object, {

                    /**
                     * @private
                     * @property {RegExp} invalidProtocolRelMatchRegex
                     *
                     * The regular expression used to check a potential protocol-relative URL match, coming from the
                     * {@link Autolinker#matcherRegex}. A protocol-relative URL is, for example, "//yahoo.com"
                     *
                     * This regular expression checks to see if there is a word character before the '//' match in order to determine if
                     * we should actually autolink a protocol-relative URL. This is needed because there is no negative look-behind in
                     * JavaScript regular expressions.
                     *
                     * For instance, we want to autolink something like "Go to: //google.com", but we don't want to autolink something
                     * like "abc//google.com"
                     */
                    invalidProtocolRelMatchRegex: /^[\w]\/\//,

                    /**
                     * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://'
                     *
                     * @private
                     * @property {RegExp} hasFullProtocolRegex
                     */
                    hasFullProtocolRegex: /^[A-Za-z][-.+A-Za-z0-9]+:\/\//,

                    /**
                     * Regex to find the URI scheme, such as 'mailto:'.
                     *
                     * This is used to filter out 'javascript:' and 'vbscript:' schemes.
                     *
                     * @private
                     * @property {RegExp} uriSchemeRegex
                     */
                    uriSchemeRegex: /^[A-Za-z][-.+A-Za-z0-9]+:/,

                    /**
                     * Regex to determine if at least one word char exists after the protocol (i.e. after the ':')
                     *
                     * @private
                     * @property {RegExp} hasWordCharAfterProtocolRegex
                     */
                    hasWordCharAfterProtocolRegex: /:[^\s]*?[A-Za-z]/,


                    /**
                     * Determines if a given match found by {@link Autolinker#processTextNode} is valid. Will return `false` for:
                     *
                     * 1) URL matches which do not have at least have one period ('.') in the domain name (effectively skipping over
                     *    matches like "abc:def"). However, URL matches with a protocol will be allowed (ex: 'http://localhost')
                     * 2) URL matches which do not have at least one word character in the domain name (effectively skipping over
                     *    matches like "git:1.0").
                     * 3) A protocol-relative url match (a URL beginning with '//') whose previous character is a word character
                     *    (effectively skipping over strings like "abc//google.com")
                     *
                     * Otherwise, returns `true`.
                     *
                     * @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
                     * @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to match
                     *   something like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
                     * @param {String} protocolRelativeMatch The protocol-relative string for a URL match (i.e. '//'), possibly with a preceding
                     *   character (ex, a space, such as: ' //', or a letter, such as: 'a//'). The match is invalid if there is a word character
                     *   preceding the '//'.
                     * @return {Boolean} `true` if the match given is valid and should be processed, or `false` if the match is invalid and/or
                     *   should just not be processed.
                     */
                    isValidMatch: function (urlMatch, protocolUrlMatch, protocolRelativeMatch) {
                        if (
                            ( protocolUrlMatch && !this.isValidUriScheme(protocolUrlMatch) ) ||
                            this.urlMatchDoesNotHaveProtocolOrDot(urlMatch, protocolUrlMatch) ||       // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost')
                            this.urlMatchDoesNotHaveAtLeastOneWordChar(urlMatch, protocolUrlMatch) ||  // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0"
                            this.isInvalidProtocolRelativeMatch(protocolRelativeMatch)                 // A protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com")
                        ) {
                            return false;
                        }

                        return true;
                    },


                    /**
                     * Determines if the URI scheme is a valid scheme to be autolinked. Returns `false` if the scheme is
                     * 'javascript:' or 'vbscript:'
                     *
                     * @private
                     * @param {String} uriSchemeMatch The match URL string for a full URI scheme match. Ex: 'http://yahoo.com'
                     *   or 'mailto:a@a.com'.
                     * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise.
                     */
                    isValidUriScheme: function (uriSchemeMatch) {
                        var uriScheme = uriSchemeMatch.match(this.uriSchemeRegex)[0];

                        return ( uriScheme !== 'javascript:' && uriScheme !== 'vbscript:' );
                    },


                    /**
                     * Determines if a URL match does not have either:
                     *
                     * a) a full protocol (i.e. 'http://'), or
                     * b) at least one dot ('.') in the domain name (for a non-full-protocol match).
                     *
                     * Either situation is considered an invalid URL (ex: 'git:d' does not have either the '://' part, or at least one dot
                     * in the domain name. If the match was 'git:abc.com', we would consider this valid.)
                     *
                     * @private
                     * @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
                     * @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to match
                     *   something like 'http://localhost', where we won't double check that the domain name has at least one '.' in it.
                     * @return {Boolean} `true` if the URL match does not have a full protocol, or at least one dot ('.') in a non-full-protocol
                     *   match.
                     */
                    urlMatchDoesNotHaveProtocolOrDot: function (urlMatch, protocolUrlMatch) {
                        return ( !!urlMatch && ( !protocolUrlMatch || !this.hasFullProtocolRegex.test(protocolUrlMatch) ) && urlMatch.indexOf('.') === -1 );
                    },


                    /**
                     * Determines if a URL match does not have at least one word character after the protocol (i.e. in the domain name).
                     *
                     * At least one letter character must exist in the domain name after a protocol match. Ex: skip over something
                     * like "git:1.0"
                     *
                     * @private
                     * @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
                     * @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to
                     *   know whether or not we have a protocol in the URL string, in order to check for a word character after the protocol
                     *   separator (':').
                     * @return {Boolean} `true` if the URL match does not have at least one word character in it after the protocol, `false`
                     *   otherwise.
                     */
                    urlMatchDoesNotHaveAtLeastOneWordChar: function (urlMatch, protocolUrlMatch) {
                        if (urlMatch && protocolUrlMatch) {
                            return !this.hasWordCharAfterProtocolRegex.test(urlMatch);
                        } else {
                            return false;
                        }
                    },


                    /**
                     * Determines if a protocol-relative match is an invalid one. This method returns `true` if there is a `protocolRelativeMatch`,
                     * and that match contains a word character before the '//' (i.e. it must contain whitespace or nothing before the '//' in
                     * order to be considered valid).
                     *
                     * @private
                     * @param {String} protocolRelativeMatch The protocol-relative string for a URL match (i.e. '//'), possibly with a preceding
                     *   character (ex, a space, such as: ' //', or a letter, such as: 'a//'). The match is invalid if there is a word character
                     *   preceding the '//'.
                     * @return {Boolean} `true` if it is an invalid protocol-relative match, `false` otherwise.
                     */
                    isInvalidProtocolRelativeMatch: function (protocolRelativeMatch) {
                        return ( !!protocolRelativeMatch && this.invalidProtocolRelMatchRegex.test(protocolRelativeMatch) );
                    }

                });
                /*global Autolinker */
                /*jshint sub:true */
                /**
                 * @protected
                 * @class Autolinker.AnchorTagBuilder
                 * @extends Object
                 *
                 * Builds anchor (&lt;a&gt;) tags for the Autolinker utility when a match is found.
                 *
                 * Normally this class is instantiated, configured, and used internally by an {@link Autolinker} instance, but may
                 * actually be retrieved in a {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag} instances
                 * which may be modified before returning from the {@link Autolinker#replaceFn replaceFn}. For example:
                 *
                 *     var html = Autolinker.link( "Test google.com", {
   *         replaceFn : function( autolinker, match ) {
   *             var tag = autolinker.getTagBuilder().build( match );  // returns an {@link Autolinker.HtmlTag} instance
   *             tag.setAttr( 'rel', 'nofollow' );
   *
   *             return tag;
   *         }
   *     } );
                 *
                 *     // generated html:
                 *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
                 */
                Autolinker.AnchorTagBuilder = Autolinker.Util.extend(Object, {

                    /**
                     * @cfg {Boolean} newWindow
                     * @inheritdoc Autolinker#newWindow
                     */

                    /**
                     * @cfg {Number} truncate
                     * @inheritdoc Autolinker#truncate
                     */

                    /**
                     * @cfg {String} className
                     * @inheritdoc Autolinker#className
                     */


                    /**
                     * @constructor
                     * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map).
                     */
                    constructor: function (cfg) {
                        Autolinker.Util.assign(this, cfg);
                    },


                    /**
                     * Generates the actual anchor (&lt;a&gt;) tag to use in place of the matched URL/email/Twitter text,
                     * via its `match` object.
                     *
                     * @param {Autolinker.match.Match} match The Match instance to generate an anchor tag from.
                     * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag.
                     */
                    build: function (match) {
                        var tag = new Autolinker.HtmlTag({
                            tagName: 'a',
                            attrs: this.createAttrs(match.getType(), match.getAnchorHref()),
                            innerHtml: this.processAnchorText(match.getAnchorText())
                        });

                        return tag;
                    },


                    /**
                     * Creates the Object (map) of the HTML attributes for the anchor (&lt;a&gt;) tag being generated.
                     *
                     * @protected
                     * @param {"url"/"email"/"twitter"} matchType The type of match that an anchor tag is being generated for.
                     * @param {String} href The href for the anchor tag.
                     * @return {Object} A key/value Object (map) of the anchor tag's attributes.
                     */
                    createAttrs: function (matchType, anchorHref) {
                        var attrs = {
                            'href': anchorHref  // we'll always have the `href` attribute
                        };

                        var cssClass = this.createCssClass(matchType);
                        if (cssClass) {
                            attrs['class'] = cssClass;
                        }
                        if (this.newWindow) {
                            attrs['target'] = "_blank";
                        }

                        return attrs;
                    },


                    /**
                     * Creates the CSS class that will be used for a given anchor tag, based on the `matchType` and the {@link #className}
                     * config.
                     *
                     * @private
                     * @param {"url"/"email"/"twitter"} matchType The type of match that an anchor tag is being generated for.
                     * @return {String} The CSS class string for the link. Example return: "myLink myLink-url". If no {@link #className}
                     *   was configured, returns an empty string.
                     */
                    createCssClass: function (matchType) {
                        var className = this.className;

                        if (!className)
                            return "";
                        else
                            return className + " " + className + "-" + matchType;  // ex: "myLink myLink-url", "myLink myLink-email", or "myLink myLink-twitter"
                    },


                    /**
                     * Processes the `anchorText` by truncating the text according to the {@link #truncate} config.
                     *
                     * @private
                     * @param {String} anchorText The anchor tag's text (i.e. what will be displayed).
                     * @return {String} The processed `anchorText`.
                     */
                    processAnchorText: function (anchorText) {
                        anchorText = this.doTruncate(anchorText);

                        return anchorText;
                    },


                    /**
                     * Performs the truncation of the `anchorText`, if the `anchorText` is longer than the {@link #truncate} option.
                     * Truncates the text to 2 characters fewer than the {@link #truncate} option, and adds ".." to the end.
                     *
                     * @private
                     * @param {String} text The anchor tag's text (i.e. what will be displayed).
                     * @return {String} The truncated anchor text.
                     */
                    doTruncate: function (anchorText) {
                        return Autolinker.Util.ellipsis(anchorText, this.truncate || Number.POSITIVE_INFINITY);
                    }

                });
                /*global Autolinker */
                /**
                 * @abstract
                 * @class Autolinker.match.Match
                 *
                 * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a
                 * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match.
                 *
                 * For example:
                 *
                 *     var input = "...";  // string with URLs, Email Addresses, and Twitter Handles
                 *
                 *     var linkedText = Autolinker.link( input, {
   *         replaceFn : function( autolinker, match ) {
   *             console.log( "href = ", match.getAnchorHref() );
   *             console.log( "text = ", match.getAnchorText() );
   *
   *             switch( match.getType() ) {
   *                 case 'url' :
   *                     console.log( "url: ", match.getUrl() );
   *
   *                 case 'email' :
   *                     console.log( "email: ", match.getEmail() );
   *
   *                 case 'twitter' :
   *                     console.log( "twitter: ", match.getTwitterHandle() );
   *             }
   *         }
   *     } );
                 *
                 * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}.
                 */
                Autolinker.match.Match = Autolinker.Util.extend(Object, {

                    /**
                     * @cfg {String} matchedText (required)
                     *
                     * The original text that was matched.
                     */


                    /**
                     * @constructor
                     * @param {Object} cfg The configuration properties for the Match instance, specified in an Object (map).
                     */
                    constructor: function (cfg) {
                        Autolinker.Util.assign(this, cfg);
                    },


                    /**
                     * Returns a string name for the type of match that this class represents.
                     *
                     * @abstract
                     * @return {String}
                     */
                    getType: Autolinker.Util.abstractMethod,


                    /**
                     * Returns the original text that was matched.
                     *
                     * @return {String}
                     */
                    getMatchedText: function () {
                        return this.matchedText;
                    },


                    /**
                     * Returns the anchor href that should be generated for the match.
                     *
                     * @abstract
                     * @return {String}
                     */
                    getAnchorHref: Autolinker.Util.abstractMethod,


                    /**
                     * Returns the anchor text that should be generated for the match.
                     *
                     * @abstract
                     * @return {String}
                     */
                    getAnchorText: Autolinker.Util.abstractMethod

                });
                /*global Autolinker */
                /**
                 * @class Autolinker.match.Email
                 * @extends Autolinker.match.Match
                 *
                 * Represents a Email match found in an input string which should be Autolinked.
                 *
                 * See this class's superclass ({@link Autolinker.match.Match}) for more details.
                 */
                Autolinker.match.Email = Autolinker.Util.extend(Autolinker.match.Match, {

                    /**
                     * @cfg {String} email (required)
                     *
                     * The email address that was matched.
                     */


                    /**
                     * Returns a string name for the type of match that this class represents.
                     *
                     * @return {String}
                     */
                    getType: function () {
                        return 'email';
                    },


                    /**
                     * Returns the email address that was matched.
                     *
                     * @return {String}
                     */
                    getEmail: function () {
                        return this.email;
                    },


                    /**
                     * Returns the anchor href that should be generated for the match.
                     *
                     * @return {String}
                     */
                    getAnchorHref: function () {
                        return 'mailto:' + this.email;
                    },


                    /**
                     * Returns the anchor text that should be generated for the match.
                     *
                     * @return {String}
                     */
                    getAnchorText: function () {
                        return this.email;
                    }

                });
                /*global Autolinker */
                /**
                 * @class Autolinker.match.Twitter
                 * @extends Autolinker.match.Match
                 *
                 * Represents a Twitter match found in an input string which should be Autolinked.
                 *
                 * See this class's superclass ({@link Autolinker.match.Match}) for more details.
                 */
                Autolinker.match.Twitter = Autolinker.Util.extend(Autolinker.match.Match, {

                    /**
                     * @cfg {String} twitterHandle (required)
                     *
                     * The Twitter handle that was matched.
                     */


                    /**
                     * Returns the type of match that this class represents.
                     *
                     * @return {String}
                     */
                    getType: function () {
                        return 'twitter';
                    },


                    /**
                     * Returns a string name for the type of match that this class represents.
                     *
                     * @return {String}
                     */
                    getTwitterHandle: function () {
                        return this.twitterHandle;
                    },


                    /**
                     * Returns the anchor href that should be generated for the match.
                     *
                     * @return {String}
                     */
                    getAnchorHref: function () {
                        return 'https://twitter.com/' + this.twitterHandle;
                    },


                    /**
                     * Returns the anchor text that should be generated for the match.
                     *
                     * @return {String}
                     */
                    getAnchorText: function () {
                        return '@' + this.twitterHandle;
                    }

                });
                /*global Autolinker */
                /**
                 * @class Autolinker.match.Url
                 * @extends Autolinker.match.Match
                 *
                 * Represents a Url match found in an input string which should be Autolinked.
                 *
                 * See this class's superclass ({@link Autolinker.match.Match}) for more details.
                 */
                Autolinker.match.Url = Autolinker.Util.extend(Autolinker.match.Match, {

                    /**
                     * @cfg {String} url (required)
                     *
                     * The url that was matched.
                     */

                    /**
                     * @cfg {Boolean} protocolUrlMatch (required)
                     *
                     * `true` if the URL is a match which already has a protocol (i.e. 'http://'), `false` if the match was from a 'www' or
                     * known TLD match.
                     */

                    /**
                     * @cfg {Boolean} protocolRelativeMatch (required)
                     *
                     * `true` if the URL is a protocol-relative match. A protocol-relative match is a URL that starts with '//',
                     * and will be either http:// or https:// based on the protocol that the site is loaded under.
                     */

                    /**
                     * @cfg {Boolean} stripPrefix (required)
                     * @inheritdoc Autolinker#stripPrefix
                     */


                    /**
                     * @private
                     * @property {RegExp} urlPrefixRegex
                     *
                     * A regular expression used to remove the 'http://' or 'https://' and/or the 'www.' from URLs.
                     */
                    urlPrefixRegex: /^(https?:\/\/)?(www\.)?/i,

                    /**
                     * @private
                     * @property {RegExp} protocolRelativeRegex
                     *
                     * The regular expression used to remove the protocol-relative '//' from the {@link #url} string, for purposes
                     * of {@link #getAnchorText}. A protocol-relative URL is, for example, "//yahoo.com"
                     */
                    protocolRelativeRegex: /^\/\//,

                    /**
                     * @private
                     * @property {Boolean} protocolPrepended
                     *
                     * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the
                     * {@link #url} did not have a protocol)
                     */
                    protocolPrepended: false,


                    /**
                     * Returns a string name for the type of match that this class represents.
                     *
                     * @return {String}
                     */
                    getType: function () {
                        return 'url';
                    },


                    /**
                     * Returns the url that was matched, assuming the protocol to be 'http://' if the original
                     * match was missing a protocol.
                     *
                     * @return {String}
                     */
                    getUrl: function () {
                        var url = this.url;

                        // if the url string doesn't begin with a protocol, assume 'http://'
                        if (!this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended) {
                            url = this.url = 'http://' + url;

                            this.protocolPrepended = true;
                        }

                        return url;
                    },


                    /**
                     * Returns the anchor href that should be generated for the match.
                     *
                     * @return {String}
                     */
                    getAnchorHref: function () {
                        var url = this.getUrl();

                        return url.replace(/&amp;/g, '&');  // any &amp;'s in the URL should be converted back to '&' if they were displayed as &amp; in the source html
                    },


                    /**
                     * Returns the anchor text that should be generated for the match.
                     *
                     * @return {String}
                     */
                    getAnchorText: function () {
                        var anchorText = this.getUrl();

                        if (this.protocolRelativeMatch) {
                            // Strip off any protocol-relative '//' from the anchor text
                            anchorText = this.stripProtocolRelativePrefix(anchorText);
                        }
                        if (this.stripPrefix) {
                            anchorText = this.stripUrlPrefix(anchorText);
                        }
                        anchorText = this.removeTrailingSlash(anchorText);  // remove trailing slash, if there is one

                        return anchorText;
                    },


                    // ---------------------------------------

                    // Utility Functionality

                    /**
                     * Strips the URL prefix (such as "http://" or "https://") from the given text.
                     *
                     * @private
                     * @param {String} text The text of the anchor that is being generated, for which to strip off the
                     *   url prefix (such as stripping off "http://")
                     * @return {String} The `anchorText`, with the prefix stripped.
                     */
                    stripUrlPrefix: function (text) {
                        return text.replace(this.urlPrefixRegex, '');
                    },


                    /**
                     * Strips any protocol-relative '//' from the anchor text.
                     *
                     * @private
                     * @param {String} text The text of the anchor that is being generated, for which to strip off the
                     *   protocol-relative prefix (such as stripping off "//")
                     * @return {String} The `anchorText`, with the protocol-relative prefix stripped.
                     */
                    stripProtocolRelativePrefix: function (text) {
                        return text.replace(this.protocolRelativeRegex, '');
                    },


                    /**
                     * Removes any trailing slash from the given `anchorText`, in preparation for the text to be displayed.
                     *
                     * @private
                     * @param {String} anchorText The text of the anchor that is being generated, for which to remove any trailing
                     *   slash ('/') that may exist.
                     * @return {String} The `anchorText`, with the trailing slash removed.
                     */
                    removeTrailingSlash: function (anchorText) {
                        if (anchorText.charAt(anchorText.length - 1) === '/') {
                            anchorText = anchorText.slice(0, -1);
                        }
                        return anchorText;
                    }

                });

                return Autolinker;


            }));

        }, {}],
        52: [function (require, module, exports) {
            'use strict';


            module.exports = require('./lib/');

        }, {"./lib/": 11}]
    }, {}, [52])(52)
});
